SG函数
Nim游戏
n堆石子 (a_1 a_2 a_3 a_4 ...... a_n)
规则(......)
(a_1 xor a_2 xor a_3 xor a_4 xor ...... xor a_n==0) ? 后手胜 : 先手胜
太简单了? ? ? hhh
上升一下规则
1.每一次可以从第1堆石子取出1或者2或者3颗
2.每一次可以从第2堆石子取出奇数颗
3.每一次可以从第3堆以及后面取出任意颗
求必胜策略
(一脸懵逼......)
不多说了 正式开始
首先我们定义一个DAG
一个入度为零的点作为起点
起点上有一个棋子 先后手沿有向边轮流移动 无法移动者lose
这就基本上把博弈论转换为了抽象模型 ---> 图论 ? ? ?
SG就是在这个DAG上面定义然后&^$@!&#%......
(1)(mex)运算
这是一个基于集合的运算
表示 最小 的不属于该集合的 非负整数
例如 (mex{0,1,3,5,6,8,9}=2)
(2)定义
当前SG函数如下 : (SG(x)=mex{SG(y)|y是x的后继})
......只有定义是没有用的
①所有出度为零的点x(我们简称为汇点) (SG(x)=0)
②(SG(x)=0) 该节点是必败点
必败态:
对于当前状态 TA的后继状态 全部 都是必胜态 那么TA就是必败态
当前状态 无法移动也就是没有后继状态 那么TA就是必败态
如果当前点是一个汇点的话 根据定义 必败无疑
但是如果不是呢 ? ? ?
根据(mex)的定义 该节点的后继节点当中所有后继节点 (SG!=0)
③(SG(x)!=0) 该节点对应状态是必胜状态
那么后继节点中一定存在(SG=0)的节点
又回到上面那个(SG(x)=0)的问题了
这样会一直递归到x是一个汇点
(SG(x)=0) 那么(TA)的前驱节点(SG!=0) 且是必胜态 那么应该就可以理解了
必胜态:
对于当前状态 TA的后继状态 至少有一个 是必败态 那么TA就是必胜态
必败态:
(1)对于当前状态 TA的后继状态 全部 都是必胜态 那么TA就是必败态
(2)当前状态 无法移动也就是没有后继状态 那么TA就是必败态
(SG(x)=0) 对应TA是汇点 或者后继结点(min{SG(y)|x can go to y}>0)
恰好对应必败态定义
(SG(x)!=0) 对应TA的后继结点 (0∈{SG(y)|x can go to y})
恰好对应必胜态定义
(3)实战
说了定义还是一脸蒙蔽 所以 手玩一下? ? ?
①普通Nim游戏(请使用SG()求解)
n堆石子 (a_1 a_2 a_3 a_4 ...... a_n)
对于任意一堆石子(a_i(1<=i<=n))
我们可以取([1,a_i])颗 那么剩余石子的范围就是([0,a-i-1])
(SG(i)=a_i)
等一下 我们相当于是把每一个石子堆看成了一个游戏
但是怎么合并呢? ? ?
直接上定理:(SG_{tot}=SG(1) xor SG(2) xor SG(3) xor SG(4) xor ...... xor SG(n))
也就是游戏的SG值就是子游戏的SG值得异或和
然后(SG_{tot}=0) 对应必败态 恰好石子堆的异或和为0 就是后手必胜
是不是有些眉目了 ? ? ?
SG定理的证明:【https://www.zhihu.com/question/51290443/answer/125105697】
因为我太菜鸡所以当然不会证明辣
②文艺Nim游戏(请使用SG()求解)
每一次可以从第1堆石子取出1或者2或者3颗
每一次可以从第2堆石子取出奇数颗
每一次可以从第3堆以及后面取出任意颗
其余不变
用SG求解
先埋一个局。。。。。。
SG模板
normal
void calc_SG(int x)
{
for(i ...枚举所有后继状态)
vis[SG[i]]=1;
}
memset(vis,0,sizeof vis);
calc_SG(x);
for(int i=0;;++i) if(!vis[i]) {SG[x]=i;break;}
时间戳优化 (卡常小技巧)
//memset(vis,0,sizeof vis) 会被卡常 所以我们尝试优化
void calc_SG(int x)
{
for(i ...枚举所有后继状态)
vis[SG[i]]=tot;
}
++tot;
calc_SG(x);
for(int i=0;;++i) if(vis[i]!=tot) {SG[x]=i;break;}
例题
我来解上面的局
对于第一种情况 这就是巴什博奕 (SG[x]=mex{SG[x-3],SG[x-2],SG[x-1]})
参考博弈树打表也是可以理解的 通式就是(SG[x]=x%4)
那么对于第二种情况(SG[x]=x%2)
也就是(SG[x]=mex{SG[x-1],SG[x-3],......,SG[(x+1)\%2]})
根据博弈树打表也可以理解
第三种情况就是(Nim)游戏 可以选择一个一个(SG)异或 也可以直接计算(SG3)
最终的(SG_{tot}=SG_1 igoplus SG_2 igoplus SG_3)
具体的见例题吧 cdy:别诶