酷代码 AI
菜单
服务商
DeepSeek字节豆包讯飞星火
更多选项

瑞士轮赛制模拟:基于实力值的动态排名与得分更新算法实现

我们来仔细分析这道题,它考察的是对 **瑞士轮赛制(Swiss-system tournament)** 的模拟能力,核心在于: - 每轮前按**当前总分 + 编号小者优先**排序; - 然后按排名 **1v2, 3v4, 5v6, ..., (2k−1)v(2k)** 配对; - 实力值高的选手**必胜**(无平局),胜者+1分,负者+0分; - 共进行 `R` 轮; - 最终输出 **R 轮后排名第 Q 的选手编号**(注意:排名从高到低,总分高者靠前;分数相同时编号小者靠前)。 --- ### ✅ 解题思路 1. **数据结构设计** - 每个选手需要记录: - `id`(编号,1-indexed) - `score`(当前总分,初始为给定值) - `power`(实力值,用于决定每场胜负) 2. **排序规则** - 主要按 `score` **降序**; - `score` 相同则按 `id` **升序**(即编号小的排前面)。 3. **模拟 R 轮比赛** - 每轮开始前: - 对所有选手按上述规则排序 → 得到当前排名列表; - 然后两两配对(索引 0&1, 2&3, ..., 2k−2&2k−1); - 对每对 `(a, b)`: - 若 `a.power > b.power` → `a.score += 1` - 否则 → `b.score += 1` 4. **最后再排一次序,取第 Q 名(索引为 Q−1)的 `id`** > ⚠️ 注意:题目中样例输入是: ``` 2 4 2 7 6 6 7 10 5 20 15 ``` 但这里明显有矛盾:第一行 `2 4 2` 表示 n=2 人?但后面给了 4 个初始分数和 4 个实力值 → 所以实际应是 **n=4**,第一行应为 `4 4 2`。 ✅ 样例输入原文可能格式错位,正确应为: ``` 4 4 2 7 6 6 7 10 5 20 15 ``` 我们按 `n=4, R=4, Q=2` 来解析样例。 --- ### 🧮 手动模拟样例(验证逻辑) #### 初始状态(n=4): | id | score | power | |----|--------|--------| | 1 | 7 | 10 | | 2 | 6 | 5 | | 3 | 6 | 20 | | 4 | 7 | 15 | → 初始排序(先按 score 降序,同分按 id 升序): - id1:7, id4:7 → id1 < id4 ⇒ [1,4,3,2] 或 [1,4,2,3]?等等,id2 和 id3 都是 6 分,id2=2 < id3=3 ⇒ id2 在 id3 前。 所以初始分数排序: - score=7: ids 1,4 → order: 1,4 - score=6: ids 2,3 → order: 2,3 → 排名序列:**[1, 4, 2, 3]** #### 第1轮对阵: - (1 vs 4): power[1]=10, power[4]=15 → 4胜 → score[4] +=1 → 7→8 - (2 vs 3): power[2]=5, power[3]=20 → 3胜 → score[3] +=1 → 6→7 更新后 scores: - id1:7, id2:6, id3:7, id4:8 #### 第2轮前重排序: scores: - id4:8 - id1:7, id3:7 → id1<id3 ⇒ 1,3 - id2:6 → 序列:[4,1,3,2] 对阵: - (4 vs 1): p4=15 > p1=10 ⇒ 4胜 → 8→9 - (3 vs 2): p3=20 > p2=5 ⇒ 3胜 → 7→8 scores now: - id1:7, id2:6, id3:8, id4:9 #### 第3轮前排序: - id4:9 - id3:8 - id1:7 - id2:6 → [4,3,1,2] 对阵: - (4 vs 3): 15 vs 20 ⇒ 3胜 → 8→9 - (1 vs 2): 10 vs 5 ⇒ 1胜 → 7→8 scores: - id1:8, id2:6, id3:9, id4:9 → id3 & id4 同为 9,id3=3 < id4=4 ⇒ id3 before id4 #### 第4轮前排序: - id3:9, id4:9 → [3,4] - id1:8 - id2:6 → [3,4,1,2] 对阵: - (3 vs 4): p3=20 > p4=15 ⇒ 3胜 → 9→10 - (1 vs 2): p1=10 > p2=5 ⇒ 1胜 → 8→9 最终 scores: - id1:9 - id2:6 - id3:10 - id4:9 排序(score↓,同分 id↑): - id3:10 - id1:9, id4:9 → id1 < id4 ⇒ id1, id4 - id2:6 → 排名:[3, 1, 4, 2] → 第2名是 **id = 1** ✅ 匹配样例输出。 --- ### ✅ Python 实现(高效、清晰) ```python n, R, Q = map(int, input().split()) scores = list(map(int, input().split())) powers = list(map(int, input().split())) # 构建选手列表:每个元素为 (score, id, power),id 是 1-indexed players = [(scores[i], i + 1, powers[i]) for i in range(n)] # 自定义排序 key:先按 score 降序,再按 id 升序 def sort_key(p): score, pid, _ = p return (-score, pid) for _ in range(R): # 每轮开始前排序 players.sort(key=sort_key) # 创建新分数列表(避免边遍历边改导致错误) new_scores = [p[0] for p in players] # 两两配对:0↔1, 2↔3, ... for i in range(0, n, 2): a = players[i] # (score, id, power) b = players[i + 1] if a[2] > b[2]: # a 实力更强 → a 胜 new_scores[i] += 1 else: # b 胜 new_scores[i + 1] += 1 # 更新 players 的 score players = [(new_scores[i], players[i][1], players[i][2]) for i in range(n)] # 最终排序,取第 Q 名(索引 Q-1) players.sort(key=sort_key) print(players[Q - 1][1]) ``` --- ### 🔍 复杂度分析 - 每轮排序:O(n log n) - R 轮:O(R × n log n) - n ≤ 2×10⁵?题没给范围,但一般 O(R n log n) 可接受(R ≤ 50, n ≤ 2×10⁵ 也 OK) --- ### 💡 开发建议(进阶优化) - 若 `n` 极大(如 1e6),可考虑用**归并思想**:因每轮只是在上轮有序基础上做局部调整(胜者+1分,仅影响相邻排名),可用两个有序队列(胜者组 + 败者组)归并,实现 O(n) 每轮 → 总 O(Rn)。 - 但本题通常无需,Python 的 `sort` 对几千/几万人足够快。 --- ### 📌 常见陷阱提醒 - ❌ 忘记“同分时编号小者靠前” → key 必须是 `(-score, id)`,不能只比 score; - ❌ 在遍历配对时直接修改 `players[i][0]`(tuple 不可变)→ 必须用新列表存分数; - ❌ 配对写成 `for i in range(n//2):` 但没检查 `i*2+1` 是否越界(但题目保证 n 为偶数); - ❌ 把“实力值高者胜”理解反了。 --- ######[AI写代码神器 | 2169点数解答 | 2026-03-20 12:13:48]

相关提问
本站限时免费提问中
实用工具查看更多
Linux在线手册 [开发类]
Jquery在线手册 [开发类]
今日油价 [生活类]
图片互转base64 [开发类]
时间转换器 [开发类]