NIM博弈+SG函数求解

ICG

给定一个有向无环图和一个起始顶点上的一枚棋子,两名选手交替的将这枚棋子沿有向边进行移动,无法移动者判负。

这个游戏可以认为是所有 Impartial Combinatorial Games 的抽象模型。也就是说,任何一个 ICG 都可以通过把每个局面看成一个顶点,对每个局面和它的子局面连一条有向边来抽象成这个“有向图游戏”。

满足以下条件的游戏是ICG:

1、有两名选手;

2、两名选手交替对棋子进行移动(move),每次一步,选手可以在有限的合法移动集合中任选一种进行移动;
3、对于游戏的任何一种可能的局面,合法的移动集合只取决于这个局面本身,不取决于轮到哪名选手操作、以前的任何操作、骰子的点数或者其它什么因素; 
4、如果轮到某名选手移动,且这个局面的合法的移动集合为空(也就是说此时无法进行移动),则这名选手负。

下 面我们就在有向无环图的顶点上定义 Sprague-Garundy 函数。首先定义 mex(minimal excludant)运算,这是施加于一个集合的运算,表示最小的不属于这个集合的非负整数。例如 mex{0,1,2,4}=3、mex{2,3,5}=0、mex{}=0。

对于一个给定的有向无环图,定义关于图的每个顶点的 Sprague-Grundy 函数 g(x)如下:g(x)=mex{ g(y) | y 是 x 的后继 }

SG 函数的性质:

1.首先,所有的 terminal position 所对应的顶点,也就是没有出边的顶点,其 SG 值为 0,因为它的后继集合是空集。

2.然后对于一个 g(x)=0 的顶点 x,它的所有后继 y 都满足 g(y)!=0。

3.对于一个 g(x)!=0 的顶点,必定存在一个后继 y 满足 g(y)=0。

以上这三句话表明,顶点 x 所代表的 postion 是 P-position 当且仅当 g(x)=0。

我们通过计算有向无环图的每个顶点的 SG 值,就可以对每种局面找到必胜策略了。

Nim 游戏的规则:

每次选择 一堆数量为 k 的石子,可以把它变成 0、变成 1、……、变成 k-1,但绝对不能保持 k不变。

变形

假设不是一枚棋子,而是n枚棋子,如何获胜?

让我们再来考虑一下顶点的 SG 值的意义。当 g(x)=k 时,表明对于任意一个0<=i<k,都存在 x 的一个后继 y 满足 g(y)=i。

也 就是说,当某枚棋子的 SG 值是 k 时,我们可以把它变成 0、变成 1、……、变成 k-1,但绝对不能保持 k 不变。

这表明,如果将 n 枚棋子所在的顶 点的 SG 值看作 n 堆相应数量的石子,那么这个 Nim 游戏的每个必胜策略都对应于原来这 n 枚棋子的必胜策略!

对于 n 个棋子,设它们对应的顶点的 SG 值分别为(a1,a2,…,an),再设局面(a1,a2,…,an)时的 Nim 游戏的一种必胜策略是把 ai 变成 k,那么原游戏的一种必胜策略就是把第 i 枚棋子移动到一个 SG 值为 k 的顶点。

其实我们还是只要证明这种多棋子的有向图游戏的局面是 P-position 当且仅当所有棋子所在的位置的 SG 函数的异或为 0。

这个证明与上节的 Bouton’s Theorem 几乎是完全相同的,只需要适当的改几个名词就行了。

刚才,为了使问题看上去更容易一些,认为 n 枚棋子是在一个有向图上移动,但如果不是在一个有向图上,而是每个棋子在一个有向图上,每次可 以任选一个棋子(也就是任选一个有向图)进行移动,这样也不会给结论带来任何变化。 所以我们可以定义有向图游戏的和(Sum of Graph Games)

设 G1、G2、……、Gn是 n 个有向图游戏,定义游戏 G 是 G1、G2、……、Gn 的和(Sum),游戏 G的移动规则是:任选一个子游戏 Gi 并移动上面的棋子。

Sprague-Grundy Theorem 就是:

g(G)=g(G1)^g(G2)^…^g(Gn)。即游戏的和的 SG 函数值是它的所有子游戏的 SG 函数值的异或。

再考虑在本文一开头的一句话:任何一个 ICG 都可以抽象成一个有向图游戏。所以“SG 函数”和“游戏的和”的概念就不是局限于有向图游戏。我们给每 个 ICG 的每个 position 定义 SG 值,也可以定义 n 个 ICG 的和。所以说当我们面对由 n 个游戏组合成的一个游戏时,只需对于每个游戏找出求它的每个 局面的 SG 值的方法,就可以把这些 SG 值全部看成 Nim 的石子堆,然后依照找 Nim 的必胜策略的方法来找这个游戏的必胜策略了!

NIM游戏

有 n 堆石子,每次可以从第 1 堆石子里取 1 颗、2 颗或 3颗,可以从第 2 堆石子里取奇数颗,可以从第 3 堆及以后石子里取任意颗,先手必胜输出Y,否则输出N

分析:

我们可以把它看作 3 个子游戏:

第 1 个子游戏只有一堆石子,每次可以取 1、2、3颗,很容易看出 x 颗石子的局面的 SG 值是 x%4。

第 2 个子游戏也是只有一 堆 石子,每次可以取奇数颗,经过简单的画图可以知道这个游戏有 x 颗石子时的 SG值是 x%2。

第 3 个游戏有 n-2 堆石子,就是一个 Nim 游戏

对于原游戏的每 个局面,把三个子游戏的 SG 值异或一下,就得到了整个游戏的 SG 值,然后就可以根据这个 SG 值判断是否有必胜策略以及做出决策了。

其实看作 3 个子游戏还是保守了些,干脆看作 n 个子游戏,其中第 1、2 个子游戏如上所述,第 3 个及以后的子游戏都是“1 堆石子,每次取几颗都可以”,称为“任取石子游戏”,这个超简 单的游戏有 x 颗石子的 SG 值显然就是 x。其实,n 堆石子的 Nim 游戏本身不就是 n 个“任取石子游戏”的和吗?

#include<bits/stdc++.h>
using namespace std;

int main()
{
	ios::sync_with_stdio(false);
	int n,t;
	cin>>t;
	while(t--){

			cin>>n;
            int x,ans=0;
			int sg1=0,sg2=0,sg3=0;
			cin>>x;//第一堆
			sg1=x%4;

			cin>>x;//第二堆
			sg2=x%2;

			for(int i=0;i<n-2;i++){
                cin>>x;
                sg3^=x;
			}
            ans=sg1^sg2^sg3;
			if(ans==0)//必败
			printf("N\n");
			else
			printf("Y\n");
		}
	return 0;
 }

总结

SG 函数与“游戏的和”的概念不是让我们去组合、制造稀奇古怪的游戏,而是把遇到的看上去有些复杂的游戏试图分成若干个子游戏,对于每个比原游戏简化很多的子游戏找出它的 SG 函数,然后全部异或起来就得到了原游戏的 SG 函数,就可以解决原游戏了。

寻找必败态

必败态就是“在对方使用最优策略时,无论做出什么决策都会导致失败的局面”。其他的局面称为胜态,值得注意的是在 胜态下做出错误的决策也有可能导致失败。此类博弈问题的精髓就是让对手永远面对必败态。

必败态和胜态有着如下性质:

1、若面临末状态者为获胜则末状态为胜态否则末状态为必败态。

2、一个局面是胜态的充要条件是该局面进行某种决策后会成为必败态。

3、一个局面是必败态的充要条件是该局面无论进行何种决策均会成为胜态。

这三条性质正是博弈树的原理,但博弈树是通过计算每一个局面是胜态还是必败态来解题,这样在局面数很多的情况下是很难做到的,此时,我们可以利用人脑的推演归纳能力找 到必败态的共性,就可以比较好的解决此类问题了。

解题思路

分析初始局势是属于哪种形态,然后根据博弈中的些结论去推导当前状态是否是必败态。

猜你喜欢

转载自blog.csdn.net/qq_40507857/article/details/81277606