Nim博弈和Sprague-Grundy定理
一、 Nim博弈
Nim游戏是指有n个堆,每堆有若干石子,现在有两个玩家轮流在堆中去取石子,要求至少取一个石子,至多取一个堆的石子,谁最先将最后的石子取完就赢了。若以[x1,x2,...,xn][x_1,x_2,...,x_n][x1,x2,...,xn]表示每堆石子的个数,则称xk(k∈1,...n)x_k(k\in1,...n)xk(k∈1,...n)为状态。这种游戏有一个规律,就是所有状态相互异或以后的值若为0,则先手(也就是第一个取石子的人)必输,反之必赢。即 result=(x1)∧(x2)∧...∧(xn)result=(x_{1})^{\wedge}(x_{2})^{\wedge}...^{\wedge}(x_n)result=(x1)∧(x2)∧...∧(xn),如果result=0result=0result=0,则先手必输。
二、 Sprague-Grundy定理
在介绍SGSGSG定理之前,首先介绍一下Minimum ExcludantMinimum\space ExcludantMinimum Excludant,Minimum ExcludantMinimum\space ExcludantMinimum Excludant是指不在集合中的最小非负整数,使用MEX(⋅)MEX(\cdot)MEX(⋅)表示。例如,集合S={0,1,3,8}S=\left\{ 0,1,3,8\right\}S={0,1,3,8},则MEX(S)=2MEX(S)=2MEX(S)=2。一个博弈当前状态的Grundy numberGrundy\space numberGrundy number为MEX({g1,g2,...,gn})MEX(\left\{g_1,g_2,...,g_n\right\})MEX({g1,g2,...,gn}),其中g1,g2,...,gng_1,g_2,...,g_ng1,g2,...,gn表示 的是我们可以从当前状态移动到的状态的Grundy numberGrundy\space numberGrundy number。其中MEX({})=0MEX(\left\{\right\})=0MEX({})=0即当一个状态不能移动到下一个状态时,Grundy numberGrundy\space numberGrundy number为000。当一个状态的Grundy numberGrundy\space numberGrundy number为0时,表示从当前状态的先手必输,反之必赢。以一个例子为例:
假设一个堆有6个coinscoinscoins,每次可以取1∼31\sim31∼3个coinscoinscoins,则Grundy(0)=0,Grundy(1)=MEX(Grundy(0))=MEX(0)=1,Grundy(2)=MEX(Grundy(0),Grundy(1))=MEX(0,1)=2,Grundy(3)=MEX(Grundy(0),Grundy(1),Grundy(2))=MEX({0,1,2})=3,Grundy(4)=MEX(Grundy(3),Grundy(2),Grundy(1))=MEX({3,2,1})=0,Grundy(5)=MEX(Grundy(4),Grundy(3),Grundy(2))=MEX({0,3,2})=1,Grundy(6)=MEX(Grundy(5),Grundy(4),Grundy(3))=MEX({1,0,3})=2Grundy(0)=0,\\ Grundy(1)=MEX(Grundy(0))=MEX(0)=1,\\ Grundy(2)=MEX(Grundy(0),Grundy(1))=MEX(0,1)=2,\\ Grundy(3)=MEX(Grundy(0),Grundy(1),Grundy(2))=MEX(\left\{0,1,2\right\})=3,\\Grundy(4)=MEX(Grundy(3),Grundy(2),Grundy(1))=MEX(\left\{3,2,1\right\})=0,\\Grundy(5) =MEX(Grundy(4),Grundy(3),Grundy(2))=MEX(\left\{0,3,2\right\})=1,\\Grundy(6)=MEX(Grundy(5),Grundy(4),Grundy(3))=MEX(\left\{1,0,3\right\})=2Grundy(0)=0,Grundy(1)=MEX(Grundy(0))=MEX(0)=1,Grundy(2)=MEX(Grundy(0),Grundy(1))=MEX(0,1)=2,Grundy(3)=MEX(Grundy(0),Grundy(1),Grundy(2))=MEX({0,1,2})=3,Grundy(4)=MEX(Grundy(3),Grundy(2),Grundy(1))=MEX({3,2,1})=0,Grundy(5)=MEX(Grundy(4),Grundy(3),Grundy(2))=MEX({0,3,2})=1,Grundy(6)=MEX(Grundy(5),Grundy(4),Grundy(3))=MEX({1,0,3})=2,由于Grundy(6)=2Grundy(6)=2Grundy(6)=2,所以只要先手就必赢,因为先手可以取走2个,这样就到达了状态4,而Grundy(4)=0Grundy(4)=0Grundy(4)=0,轮到对手先手,必输。
上述游戏只有一个堆,如果有多个堆,则一个博弈的Grundy numberGrundy\space numberGrundy number为子博弈的Grundy numberGrundy\space numberGrundy number的异或(即nim sumnim\space sumnim sum)后的值。如果值为0则必输,这个就是sprague grundysprague\space grundysprague grundy定理。
如果将nimnimnim博弈和sprague grundy theoremsprague\space grundy\space theoremsprague grundy theorem联系起来的话,假设有nnn堆石子[x1,x2,...,xn][x_1,x_2,...,x_n][x1,x2,...,xn],如果至少选择一个,至多选择一堆,则Grundy(x1)=MEX(Grundy(0),Grundy(1),...,Grundy(x1−1))=x1Grundy(x_1)=MEX(Grundy(0),Grundy(1),...,Grundy(x_1-1))=x_1Grundy(x1)=MEX(Grundy(0),Grundy(1),...,Grundy(x1−1))=x1,同理可得Grundy(xn)=xnGrundy(x_n)=x_nGrundy(xn)=xn,因此,nim sumnim\space sumnim sum为(x1)∧(x2)∧...∧(xn)(x_1)^{\wedge}(x_2)^{\wedge}...^{\wedge}(x_n)(x1)∧(x2)∧...∧(xn)。
求Grundy numberGrundy\space numberGrundy number的过程可以用如下代码表示:
int a[m];//给定的可选择的序列,大小为m;
int g[maxn];
//mex运算 找到集合中最小的非负整数
int mex(set<int>& s)
{
int a = 0;
while(s.count(a))
a++;
return a;
}
int main()
{
g[0] = 0;
for(int i = 1; i < n; i++)
{
set<int> s; // s保存当前状态可以到达的所有其他状态的grundy值
for(int j = 0; j < m; j++)
{
s.insert(g[i - a[j]]);
}
g[i] = mex(s); //当前状态的grundy值
}
}
求得所有堆的GrundyGrundyGrundy值以后,将所有的值异或,结果为0的话则先手必输。
本文介绍了Nim博弈及其获胜策略,通过异或操作判断先手胜负。接着阐述了Sprague-Grundy定理,利用Minimum Excludant(MEX)求解各状态的Grundy number,确定博弈的最终结果。当nim sum为0时,先手必败。

1546

被折叠的 条评论
为什么被折叠?



