Nim游戏
Nim游戏是博弈论中最经典、最重要的模型之一,也是巴什博弈的多维推广。
一、问题定义
-
有 多堆 石子(比如 3 堆、4 堆...)
-
每堆石子数量分别为 a1,a2,...,aka1,a2,...,ak
-
每人每次选择 其中一堆 ,取 任意正整数颗(至少1颗,至多全取完)
-
取光者赢(标准规则)
-
双方最优策略,问先手是否必胜
与巴什博弈的区别
| 维度 | 巴什博弈 | Nim游戏 |
|---|---|---|
| 堆数 | 1堆 | 多堆 |
| 每步限制 | 1 ~ m 颗 | 任意颗(整堆) |
| 核心结论 | 模周期 | 异或和 |
二、核心结论(必背!)
Nim游戏的结论极其简洁优美:
text
若 a₁ XOR a₂ XOR a₃ XOR ... XOR aₖ == 0
则 先手必败(P态)
否则 先手必胜(N态)
其中 XOR 是按位异或运算。
三、为什么是异或?直观理解
1. 终局状态
-
终局:所有堆都是 0
-
0⊕0⊕...⊕0=00⊕0⊕...⊕0=0 ✅ 必败态
2. 必败态性质
当异或和为 0 时:
- 无论你从哪一堆取多少颗(不能为0),新状态的异或和 一定 ≠ 0
3. 必胜态性质
当异或和 ≠ 0 时:
- 一定存在一种取法,使新状态的异或和变为 0(证明用到了异或的数学性质)
4. 核心逻辑链
text
必败态(0) → 只能走到必胜态(≠0)
必胜态(≠0) → 存在一步走到必败态(0)
四、举例验证
例子1:3堆 (3, 4, 5)
text
3 ⊕ 4 ⊕ 5 = ?
3 = 011
4 = 100 → 异或 = 111(7) ⊕ 5
5 = 101
--------
7 ⊕ 5 = 111 ⊕ 101 = 010(2) ≠ 0
先手 必胜
例子2:3堆 (3, 5, 6)
text
3 = 011
5 = 101 → 异或 = 110(6) ⊕ 6 = 0
6 = 110
先手 必败
五、获胜策略(如何走)
当异或和 ≠ 0 时,先手要找到 某一堆,使其数量变为:
text
新数量 = 原数量 ⊕ 总异或和
条件:新数量 < 原数量(因为只能减少)
例:(3, 4, 5) 异或和 = 2
-
堆1: 3 ⊕ 2 = 1 (< 3) ✅ 可取,将3变为1 → 新状态(1,4,5) 异或=0
-
堆2: 4 ⊕ 2 = 6 (> 4) ❌ 不能
-
堆3: 5 ⊕ 2 = 7 (> 5) ❌ 不能
所以唯一正确走法:从第1堆取2颗,变成 (1,4,5)
六、取光者输(反常Nim / Misère Nim)
特殊情况
当 所有堆都只有 1 颗石子 时,规则特殊:
text
- 若堆数 % 2 == 0 → 必胜
- 若堆数 % 2 == 1 → 必败
一般情况(不全是 1)
结论 与标准Nim相同:
text
异或和 == 0 → 先手必败
否则 → 先手必胜
完整判断流程
python
def misere_nim(stones):
# stones: 列表,每堆石子数
all_one = all(x == 1 for x in stones)
if all_one:
return len(stones) % 2 == 1 # 奇数堆输?
# 实际上:奇数堆 → 先手必败(输出NO)
# 需要根据题目要求调整
else:
xor_sum = 0
for x in stones:
xor_sum ^= x
return xor_sum != 0
七、常见变形与考点
| 变形 | 结论变化 |
|---|---|
| 标准Nim(取光者赢) | 异或和判断 |
| Misère Nim(取光者输) | 全1时单独处理,否则同标准 |
| 每次只能取 ≤ m 颗(每堆有上限) | 转化为每个堆的Grundy数,再异或(SG定理) |
| 多堆 + 每堆取法不同 | SG定理通用解法 |
| 可以同时从多堆取 | 规则变化,不一定是Nim |
八、与巴什博弈的关系
巴什博弈是 1堆的Nim游戏(但每步有限制)
巴什博弈→Nim的关键推广:
-
1堆(有上限) → 巴什
-
多堆(无上限) → Nim
-
多堆(每堆有上限) → 需要SG定理
text
SG定理核心:
1. 每堆独立看作一个子游戏
2. 计算每堆的SG值
3. 所有SG值异或 == 0 → 先手败
九、一句话总结
Nim游戏 = 多堆石子的异或和运算
异或和 = 0 → 先手必败
先手策略:让下一状态异或和变为 0
十、快速判断模板
python
def nim_win(stones):
xor_sum = 0
for x in stones:
xor_sum ^= x
return "YES" if xor_sum != 0 else "NO"
掌握了Nim,你就掌握了组合博弈论的核心工具 ,可以进一步学习SG定理,解决几乎所有公平组合游戏问题。
如果只能从最左端或者最右端取呢
很好的问题!这个变种规则完全改变了博弈的性质。
问题重定义
-
有 一排 石子(或数组/序列)
-
每堆石子有不同数量(不是每堆独立,而是排在一条线上)
-
每次只能从 最左端 或 最右端 取 整堆(或取这堆里任意数量?需要明确)
-
取光者赢
⚠️ 关键区分 :你问的实际上是 "取石子游戏"的另一个经典变种,不再是 Nim/巴什的范畴。
你需要先确认题目具体规则:
情况1:每次从一端取 整堆(堆大小固定)
比如序列:[3, 5, 2, 7, 4]
规则
-
每次只能拿最左或最右的 那一整堆
-
拿走该堆全部石子
-
取光者赢
这是什么问题?
→ 完全信息双人零和博弈 ,可以用 区间DP 解决
解法:先手最大得分差
设 dp[i][j] 表示当前剩余区间 [i, j] 时,先手能获得的最大净胜分(自己得分 - 对方得分)
转移:
text
dp[i][j] = max(
a[i] - dp[i+1][j], // 取左端
a[j] - dp[i][j-1] // 取右端
)
边界:dp[i][i] = a[i]
最终判断:dp[0][n-1] > 0 → 先手必胜
举例
[3, 9, 1, 2]
计算:
-
dp[3][3]=2
-
dp[2][3]=max(1-2, 2-1)=max(-1,1)=1
-
dp[1][3]=max(9-1, 2-1)=max(8,1)=8
-
dp[0][3]=max(3-8, 2-8)=max(-5,-6)=-5 → 先手必败
情况2:从一端取 1~m 颗(该端堆无限/足够多)
比如一长排石子,每堆数量很大
规则
-
每次只能从最左端或最右端的堆里取 1~m 颗
-
取光者赢
本质
→ 退化成了巴什博弈?不完全是,因为两端独立
实际上这是一个 "两端巴什" 问题,也可以用区间DP + SG定理分析
常见算法竞赛真题形式
题目1:两端取整堆(LeetCode 877. Stone Game)
-
总石子数奇数
-
每次取左或右整堆
-
得分高者赢
结论 :先手 必胜(因为有对称策略)
题目2:两端取任意正整数颗(POJ 1067 取石子游戏)
-
两堆石子
-
每次可从一堆取任意 或 从两堆取相同数量
-
威佐夫博弈(Wythoff Game)
结论:黄金比例判断
总结:不同限制条件下的结论
| 规则 | 类型 | 判断方法 |
|---|---|---|
| 多堆独立,每堆可取任意 | Nim | 异或和 |
| 单堆,取1~m | 巴什 | n % (m+1) |
| 一排,只能取两端整堆 | 区间DP | dp[i][j] 正负 |
| 一排,每端取1~m | 区间DP + SG | 复杂 |
| 两堆,取任意/相同 | 威佐夫 | 黄金分割 |