该问题属于博弈论中的公平博弈(Impartial Games)变体,但由于其对取物顺序的严格限制(必须从第一个非空堆取样),其核心逻辑不同于标准的 Nim 博弈,而更接近于前缀控制博弈。
一、 问题分析
问题的核心约束在于必须从第一个非空堆取走任意正整数张全家福。这意味着,游戏的进行路径在很大程度上是被“序”约束的。只有当第 堆被取空后,玩家才能操作第
堆。
这一约束改变了博弈的自由度:在标准 Nim 博弈中,玩家可以任选一堆来改变异或和;但在本题中,每一堆的决策权力是按顺序移交的。因此,博弈的关键变成了:谁能掌握对“关键堆”的控制权。
二、 算法:关键堆与控制权转移
1. “1”的强制性
若第 堆的数量
,当前轮次的玩家没有选择,必须取走这一张。这导致该玩家不可避免地将操作下一堆(第
堆)的机会交给了对手。
2. “
”的决策权(控制堆)
若第 堆的数量
,当前玩家拥有博弈主动权。该玩家可以采取以下两种策略之一:
- 策略 A(全部取走):取走整堆
。此时,下一堆
的先手权交给对手。
- 策略 B(保留 1 个):取走
张。此时,第
堆还剩 1 张,轮到对手时由于只能从第一个非空堆取,对手必须取走这最后的 1 张。随后,当前玩家重新获得第
堆的先手权。
结论:第一个遇到 的玩家可以根据后序子游戏的胜负情况,自由决定是由自己还是由对手开启下一堆。在最优策略下,第一个遇到
的玩家必然能够通往获胜状态,除非该堆已经是最后一堆。若是最后一堆且
,当前玩家直接取完获胜。
3. 边界情况:全为 "1"
若序列中不存在 的堆(即所有
),则每位玩家都被强制交替执行操作。此时胜负完全取决于堆的数量
的奇偶性:
为奇数:Alice 获胜。
为偶数:Bob 获胜。
三、 代码实现
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int T;
cin >> T;
while (T--) {
int n;
cin >> n;
int winPos = -1;
for (int i = 1; i <= n; i++) {
int a;
cin >> a;
if (winPos == -1 && a > 1) {
winPos = i;
}
}
if (winPos != -1) {
cout << (winPos % 2 == 1 ? "Alice\n" : "Bob\n");
} else {
cout << (n % 2 == 1 ? "Alice\n" : "Bob\n");
}
}
}

京公网安备 11010502036488号