跳转至

BISHI9 田忌赛马

中等通过率 47.72%python3样例通过牛客 AC

牛客原题  源码

讲解章节排序贪心偏序集与 Dilworth 定理

一句话

三局两胜,齐威王的出场顺序已知,田忌可任意排列自己的三匹马。

解题思路

这题考什么

「数据小到能把所有方案枚举完」的判断力。经典的田忌赛马讲贪心 (用最慢的马去消耗对方最快的马),但那套策略是马匹数量很大时才需要的。 本题马匹数固定为 3,田忌的出场顺序一共只有 3! = 6 种, 把 6 种全部试一遍、看有没有一种能赢下两局,得到的就是精确答案, 连带把「贪心是否正确」这个证明义务一起省掉了。 能枚举就不要猜策略,这是入门阶段最该先立住的一条。

itertools.permutations(a) 直接产出 a 的全部排列;把某个排列 p 与 齐威王的 v 用 zip 对齐,第 k 对就是第 k 局的对阵双方。

数据规模与复杂度

输入只有一组,6 种排列 * 3 局比较 = 18 次比较,O(1)。 数据量这么小,用 input() 逐行读即可,不必上 sys.stdin.buffer 的快读。

坑在哪

  1. 「严格大于」才算赢,速度相等是平局、双方都不得分。 把 x > y 写成 x >= y,样例 2(v = 2 2 2,a = 2 2 3)就会判成 Yes, 而正确答案是 No;
  2. 三局两胜的条件是「赢的局数 >= 2」,不是「赢的比输的多」: 两胜一负、两胜一平都算赢,一胜两平只赢一局,不算;
  3. 齐威王的顺序是给定的、不能重排,可以调整的只有田忌那一行。

样例复核

v = (3, 2, 1)、a = (1, 2, 3):取排列 (1, 3, 2) 对上 (3, 2, 1), 三局依次是输、赢、赢,赢下 2 局,输出 Yes,与样例一致。

参考实现

solutions/BISHI9.py
1
2
3
4
5
6
7
8
9
from itertools import permutations

v = list(map(int, input().split()))      # 齐威王按上场顺序的三匹马,顺序固定
a = list(map(int, input().split()))      # 田忌的三匹马,顺序可以任意重排

# 枚举田忌三匹马的所有出场顺序,只要有一种能赢下至少两局即可。
# sum(x > y for ...) 利用了 True == 1:把「本局是否赢」直接累加成胜场数。
ok = any(sum(x > y for x, y in zip(p, v)) >= 2 for p in permutations(a))
print("Yes" if ok else "No")
[:octicons-arrow-left-16: BISHI8](BISHI8.md) [BISHI10 :octicons-arrow-right-16:](BISHI10.md)