博弈论——sg,mex
sg性质:1.在末态的状态点为N态。
2.P态的下一步有一个是N态
3.N态的下一步全部是P态。
当然这是对于单点一个游戏的情形,也相当于NIM只有一堆石子。
mex(minimal excludant),很俗地可以解释为:mex{S}表示S集合中从0开始,最小未出现的数字。
关于sg与mex的关系,可以引用这里http://www.cnblogs.com/Knuth/archive/2009/09/05/1561007.html的一段话:
对于一个给定的有向无环图,定义关于图的每个顶点的Sprague-Garundy函数g如下:g(x)=mex{ g(y) | y是x的后继 }。
来看一下SG函数的性质。首先,所有的terminal position所对应的顶点,也就是没有出边的顶点,其SG值为0,因为它的后继集合是空集。然后对于一个g(x)=0的顶点x,它的所有后继y都满足g(y)!=0。对于一个g(x)!=0的顶点,必定存在一个后继y满足g(y)=0。
以上这三句话表明,顶点x所代表的postion是P-position当且仅当g(x)=0(跟P-positioin/N-position的定义的那三句话是完全对应的)。
关于sg叠加的效果,很神奇发现它们满足sg(G) = sg(G1)^sg(G2)^……^sg(Gn)。对于与博弈有关的核心就是这些了。多刷刷题,自然心里就明了了。
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 using namespace std; 5 int sg[210][210]; 6 int stamp[210*210]={0},stamps=1; 7 int sgx(int r,int c){ 8 stamps++; 9 for(int i=2;i<=r-i;i++) // 1 c(只有一行)【r-1 c】 不能被继续,故需要从2开始。 10 stamp[sg[i][c]^sg[r-i][c]] = stamps; 11 for(int i=2;i<=c-i;i++) 12 stamp[sg[r][i]^sg[r][c-i]] = stamps; 13 for(int i=0;;i++) 14 if(stamp[i] < stamps) 15 { 16 sg[r][c] = i; 17 break; 18 } 19 return sg[r][c]; 20 } 21 int main() 22 { 23 for(int i=1;i<210;i++) 24 sg[1][i] = sg[i][1] = 1; 25 26 for(int i=2;i<210;i++) 27 for(int j=i;j<210;j++) 28 sg[i][j] = sg[j][i] = sgx(i,j); 29 int n,m; 30 while(scanf("%d%d",&n,&m) != EOF){ 31 if(sg[n][m]) printf("WIN\n"); 32 else printf("LOSE\n"); 33 } 34 return 0; 35 }