博弈论 随记(SG函数)

博弈论 随记

博弈论

1. 简单博弈

    正推/反推。纸上画画直观图(ven图,条形图等),找必胜区间和必败区间。一般此类问题都有同余的必胜点。

HDU4764/**/

2. Nim游戏

    有若干堆石子,每堆石子的数量ai都是有限的,合法的移动是“选择一堆石子并拿走若干颗(不能不拿)”,如果轮到某个人时所有的石子堆都已经被拿空了,则判负(因为他此刻没有任何合法的移动)。

对于(a1,a2,a3,…an)局面: a1^a2^...^an==0 (^为异或)clip_image002 为P-position,先手必败/**/

{/*

对N/P状态的理解:N-position (Now,当前状态)现在轮到move的人有必胜策略的局面。

P-position(Previous,上次状态) 上一次move的人有必胜策略的局面。

博弈论 随记(SG函数)_第1张图片

若A局面的子局面a[i]中存在P,则A为N。

若A局面的子局面a[i]全部为N,则A为P。

递归,子状态推出开始局面(3,3)的N/P。

用DP或者记忆化搜索降低时间复杂度。

*/}

3. SG函数

例1.n堆石子,每次可以从第1堆石子里取1颗、2颗或3颗,可以从第2堆石子里取奇数颗,可以从第3堆及以后石子里取任意颗……

先看例2.一个有向无环图和一个起始顶点上的一枚棋子,两名选手交替的将这枚棋子沿有向边进行移动,无法移动者判负。事实上,这个游戏可以认为是所有Impartial Combinatorial Games的抽象模型。

/**/


首先定义mex(minimal excludant)运算,这是施加于一个集合的运算,表示最小的不属于这个集合的非负整数。例如mex{0,1,2,4}=3、mex{2,3,5}=0、mex{}=0。

对于一个给定的有向无环图,定义关于图的每个顶点的Sprague-Grundy函数g如下:g(x)=mex{ g(y) | y是x的后继 }。g(x)含义不理解先看SG函数的性质

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/N-position的 定义的那三句话是完全对应的)。我们通过计算有向无环图的每个顶点的SG值,就可以对每种局面找到必胜策略了。

当g(x)=k时,表明对于任意一个0<=i不知道你能不能根据这个联想到Nim游戏, Nim游戏的规则就是:每次选择一堆数量为k的石子,可以把它变成0、变成1、……、变成k-1,但绝对不能保持k不变。这表明,如果将n枚棋子所在的顶点的SG值看作n堆相应数量的石子,那么这个Nim游戏的每个必胜策略都对应于原来这n枚棋子的必胜策略!

设G1、G2、……、Gn是n个有向图游戏,定义游戏G是G1、G2、……、Gn的和(Sum),游戏G的移动规则是:任选一个子游戏Gi并移动上面的棋子。Sprague-Grundy Theorem就是:g(G)=g(G1)^g(G2)^...^g(Gn)。也就是说,游戏的和的SG函数值是它的所有子游戏的SG函数值的异或。

刚才,我为了使问题看上去更容易一些,认为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函数值的异或。

所以说当我们面对由n个游戏组合成的一个游戏时,只需对于每个游戏找出求它的每个局面的SG值的方法,就可以把这些SG值全部看成Nim的石子堆,然后依照找Nim的必胜策略的方法来找这个游戏的必胜策略了!(Nim其实就是n个从一堆中拿石子的游戏求SG的变型,总SG=n个sg的异或)。(very important)


解题模型:

   1.把原游戏分解成多个独立的子游戏,则原游戏的SG函数值是它的所有子游戏的SG函数值的异或。

      sg(G)=sg(G1)^sg(G2)^...^sg(Gn)。

   2.分别考虑没一个子游戏,计算其SG值。

     SG值的计算方法:(重点

       1.可选步数为1~m的连续整数,直接取模即可,SG(x) = x % (m+1);

2.可选步数为任意步,SG(x) = x;

3.可选步数为一系列不连续的数,用模板计算。

       模板1:打表

  

//f[]:可以取走的石子个数  
//sg[]:0~n的SG函数值  
//hash[]:mex{}  
int f[N],sg[N],hash[N];       
void getSG(int n)  
{  
    int i,j;  
    memset(sg,0,sizeof(sg));  
    for(i=1;i<=n;i++)  
    {  
        memset(hash,0,sizeof(hash));  
        for(j=1;f[j]<=i;j++)  
            hash[sg[i-f[j]]]=1;  
        for(j=0;j<=n;j++)    //求mes{}中未出现的最小的非负整数  
        {  
            if(hash[j]==0)  
            {  
                sg[i]=j;  
                break;  
            }  
        }  
    }  
}  
例题: Matrix Game,Again Stone Game,Partitioning Game

     

  模板二:DFS

//注意 S数组要按从小到大排序 SG函数要初始化为-1 对于每个集合只需初始化1遍  
//n是集合s的大小 S[i]是定义的特殊取法规则的数组  
int s[110],sg[10010],n;  
int SG_dfs(int x)  
{  
    int i;  
    if(sg[x]!=-1)  
        return sg[x];  
    bool vis[110];  
    memset(vis,0,sizeof(vis));  
    for(i=0;i=s[i])  
        {  
            SG_dfs(x-s[i]);  
            vis[sg[x-s[i]]]=1;  
        }  
    }  
    int e;  
    for(i=0;;i++)  
        if(!vis[i])  
        {  
            e=i;  
            break;  
        }  
    return sg[x]=e;  
} 




一般DFS只在打表解决不了的情况下用,首选打表预处理。

LightOJ 1315Game of Hyper Knights,此题打表不好处理,只好DFS。


3.计算sg(G)=sg(G1)^sg(G2)^...^sg(Gn),
    sg(G)=0,即P-Position,即先手比败。





你可能感兴趣的:(博弈论,随记)