一、巴什博弈
巴什博弈是最简单的组合游戏,大概是这样的:
只有一堆n个物品,两人轮流从这堆物品中取物,现在规定每次至少取1个,最多取m个,
最后取完的人胜.这道题我们可以使用P/N分析找到必胜点和必败点.分析如下:
我们假设最多能取3个:
我们可以很容易看出n%(m+1)=0的点都是必败态.因为在必败点上无论你怎么取,
它的后继状态都是N.
变形:如果我们规定最后取完的人输,结果又会如何.
二、威佐夫博弈
问题描述:首先有两堆石子,博弈双方每次取一堆石子中的任意个,不能不取,
或者取两堆石子中的相同个,先取完者胜利.P/N分析:
这样我们就可以找到必败状态,我们假设(a[],b[]),double k=(sqrt(5)+1)/2
(0,0)
(1,2) j=b-a=1 a=j*k
(3,5) j=b-a=2 a=j*k
(4,7) j=b-a=3 a=j*k
(6,10) j=b-a=4 a=j*k
(8,13) j=b-a=5 a=j*k
这里来说一个结论(证明过程略)
以上说明:a=(b-a)*k是一个必败态
三、Nim博弈
问题描述:有若干对石子,每堆石子的数量都是有限的,合法的移动式"选择一堆石子并拿走
若干颗(不能不拿)",如果轮到某个人时所有的石子堆都已经被拿空了,那么他就输了.
我们假设有三堆石子,分析如下:
1.(0,0,0) 显然是必败态
2.(0,n,n) 必败态 为什么? 不论我们从任意一堆中取走多少,对手都能在另外一堆中取走同样多的石子,
直到取到(0,0,0)
3.(1,2,3) 必败态 不论我们怎么取,对手都可以把局势变成(0,n,n)的情况
现在有一个定理,状态(x1,x2,x3)为必败态当且仅当x1^x2^x3=0.这里的^是二进制的逐位异或操作,
也称Nim和.假设有一个状态Nim不为0,那么这个状态一定可以通过一种取法使状态到达x1^x2^x3=0.
四、SG函数
对于任意x,定义SG(x)=mex(S),其中S是x的后继状态的SG函数值的集合,mex(S)表示不在S内的最
小的非负整数.终态(0,0,0)没有后继状态,SG=0;如果一个状态的后继状态中SG为0,那么他一定是
必胜态,否则一定是必败态.
SG代表的值是当前状态下达不到的后继状态的值.
SG函数模板:
//f[N]:可改变当前状态的方式,N为方式的种类,f[N]要在getSG之前先预处理
//SG[]:0~n的SG函数值
//S[]:为x后继状态的集合
int f[N],SG[MAXN],S[MAXN];
void getSG(int n){
int i,j;
memset(SG,0,sizeof(SG));
//因为SG[0]始终等于0,所以i从1开始
for(i = 1; i <= n; i++){
//每一次都要将上一状态 的 后继集合 重置
memset(S,0,sizeof(S));
for(j = 0; f[j] <= i && j <= N; j++)
S[SG[i-f[j]]] = 1; //将后继状态的SG函数值进行标记
for(j = 0;; j++) if(!S[j]){ //查询当前后继状态SG值中最小的非零值
SG[i] = j;
break;
}
}
}