文章目录
0. 参考文章
https://blog.csdn.net/weixin_38686780/article/details/82940573
https://blog.csdn.net/qq_41552508/article/details/89159952
https://www.zhihu.com/question/27467617
1. 平等博弈
1.1 常见概念及定理
1.1.1 组合游戏
公平组合游戏ICG – Impartial Combinatorial Games
游戏的胜负仅仅取决于当前状态,与谁在玩没有关系。
判定:
- 2人博弈
- 当前状态的下一个状态的个数有限
- 每个状态,两人操作集合相同
- 交替移动
- 一个人不能移动就为输
- 有限步内终止
1.1.2 P状态与N状态
P - 必败态
N - 必胜态
- 所有终止的状态是P状态
- 能一步到达P状态的是N状态
- 每一步都将到达N状态的为P状态
1.1.3 SG函数和SG定理
sg函数值的意义,如果
s
g
(
x
)
=
0
sg(x)=0
sg(x)=0,那么x是必败态,否则x是必胜态。
定义:
s
g
(
x
)
=
m
i
n
{
n
≥
0
∣
n
=
s
g
(
y
)
,
y
∈
F
(
x
)
}
sg(x)=min\{n\geq 0|n=sg(y),y\in F(x)\}
sg(x)=min{n≥0∣n=sg(y),y∈F(x)}
F
(
x
)
F(x)
F(x)表示x所有的下一个状态的集合。
定义mex函数为不在一个集合里的最小非负整数。则
s
g
(
x
)
=
m
e
x
{
s
g
(
y
)
∣
y
∈
F
(
x
)
}
sg(x)=mex\{sg(y)|y\in F(x)\}
sg(x)=mex{sg(y)∣y∈F(x)}
SG定理:
s
g
(
x
1
,
x
2
,
.
.
.
,
x
n
)
=
s
g
(
x
1
)
⊕
s
g
(
x
2
)
⊕
.
.
.
⊕
s
g
(
x
n
)
sg(x_1,x_2,...,x_n)=sg(x_1) \oplus sg(x_2)\oplus ... \oplus sg(x_n)
sg(x1,x2,...,xn)=sg(x1)⊕sg(x2)⊕...⊕sg(xn)
求sg函数代码:
const int maxn = 5e4 + 10;
//f[i]代表可行的转移方式 k代表方式总数
int f[maxn], k, sg[maxn];
bool vis[maxn];
void getsg(int n) {
memset(sg, 0, sizeof sg);
for (int i = 1; i <= n; ++i) {
memset(vis, 0, sizeof vis);
for (int j = 1; f[j] <= i && j <= k; ++j) {
vis[sg[i - f[j]]] = 1;
}
for (int j = 0;; ++j)
if (!vis[j]) {
sg[i] = j;
break;
}
}
}
1.2 常见模型
1.2.1 巴什博弈
一堆n个物品,每人每次轮流从中取出
1
−
m
1 - m
1−m个,最后取光者胜。
结论:如果
n
%
(
m
+
1
)
=
=
0
n \% (m+1)==0
n%(m+1)==0那么后手胜,否则先手获胜。
1.2.2 nim博弈
两个人玩取石子游戏,共有N堆石子,每个人每次可以从一堆石子里面任意多个石子,最后取光者胜。
结论:亦或和为0先手必败,否则先手必胜。
阶梯nim:n级台阶,每级台阶上放有石子。每人每次选一级台阶上的若干石子移到下一层。第0层为地面。不能移动的为输。
结论:奇数级台阶的亦或和为0先手必败,否则先手必胜。
1.2.3 反nim博弈
将nim改为最后取的人输。
必胜态有两种:
- 所有石堆个数都是1,且有偶数堆。
- 如果存在某堆个数不为1,那么亦或和不为0。
1.2.4 威佐夫博弈
两个人玩取石子游戏,共有2堆石子,每个人可以选择从一堆石子里面取石子,也可以选择从两堆石子里面取相同数量的石子,最后取光者胜。
结论:必败局势为(a,b)(a<b),满足
a
=
(
i
n
t
)
(
b
−
a
)
∗
5
+
1
2
a=(int)(b-a)*\frac{\sqrt{5}+1}{2}
a=(int)(b−a)∗25+1
代码:
if (x > y)swap(x, y);
double r = (sqrt(5.0) + 1) / 2;
if ((int) ((double) (y - x) * r) == x)cout << "houshou" << endl;
else cout << "xianshou" << endl;
1.2.5 Moore’s Nimk
两个人玩取石子游戏,共有N堆石子,每个人每次可以从至多k堆石子里面任意多个石子,最后取光者胜。
结论:把n堆石子的石子数用二进制表示,统计每个二进制位上1的个数,若每一位上1的个数mod(k+1)全部为0,则必败。
1.2.6 Fibonacci博弈
1堆石子有n个,两人轮流取。先取者第1次可以取任意多个,但不能全部取完。以后每次取的石子数不能超过上次取子数的2倍。最后取光者胜。
结论:先手必胜当且仅当识字数n不是Fibonacci数。