Game Theory SG function - algorithm description and examples

First, the basic concept:

1. Impartial Combinatorial Games (ICG) a combination of fair play:

    1. The two players

    2. alternately operate some predetermined games, every time operation, the player may be limited (operation must be legal) optionally one collection.

    3. For any possible game situation, legitimate set of operations depends only on the situation in itself, it does not depend on other factors (with the players, independent of all previous operations)

    4. If the current players can not be a legitimate operation, that the legitimate collection is empty, it is negative.

2. P-position and N-position definition and properties:

    P-position: flip win

    N-position: upper hand win

    definition:

    1. can not make any moves situation is P-position.
    2. P-position can be moved into the situation is N-position.  
    3. The moves are all N-position results in the situation is that P-position.

    nature:

    1. All endpoints are P-position.
    2. N-position from any operation, at least one way into the P-position.
    3. In any case the operation, from the P-position can only enter the N-position.

3. mex operation (minimal excludant negative minimum operation):

    This does not belong to the minimum set of non-negative integers.

    如 mex {0,1,2,4} = 3, mex {2,3,5} = 0, mex {} = 0.

4. SG functions: 

    Let x be any game state, S is the set of subsequent game state
    
    of the SG (x) = mex (S )
    
    x-There are three successor states SG (a), SG (b  ), SG (c)
    
    then SG (x) = mex {SG (a) SG (b), SG (c)}. (SG is a state subsequent game status value of the smallest negative)

    Necessarily the final state set S is an empty set, the final state is a function of SG SG (x) = 0, for the P-position

    SG function portion may Reference Examples: https://blog.csdn.net/bestsort/article/details/88197959

    SG can see the value function are recursive nature.

5. Nim (of Nim) Game:

There are any heap objects, the number of items per stack is arbitrary, the two sides take turns to reap items, each can only take part or all of the items from a pile of articles, at least take one, take one item to the last man to win (i.e., without fail article preferably human) .

6. Anti Nimes (anti-Nim) Game:

In Nimes Game finished the last man to take the winner of a stone, but a stone to get to the final loser is anti Nimes Game.

 

Second, the conclusions and algorithms:

 1. SG function:

  (By meter)

//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;
        }
    }
}

(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<n;i++)
    {
        if(x>=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;
}

 

2. Nim game:

For the situation of a game Nim (a1, a2, ..., an), which is the P-position if and only if a1 ^ a2 ^ ... ^ an = 0, where ^ represents a bitwise exclusive-or (XOR) operation.

3. anti-Nim game: 

Win situation is determined in the anti-Nim gaming two conditions, any point to meet the upper hand can win, i.e. win situation (N-position).  

    1.   The number of stones piled each XOR result is not equal to 0, and there is greater than the number of stones a stone stack.

    2.   The number of stones piled each XOR result equals 0, and all of a number of stones all stack.

4. ICG solving the model: 

The complexity of a game into a plurality of independent sub-game, considered separately for each sub-game, which is calculated SG value, the original value is the game SG SG function values ​​of all the sub-game or exclusive, i.e. sg (G) = sg (G1) ^ sg (G2) ^ ... ^ sg (Gn).

SG value is calculated:

1. Optional step number 1 ~ m successive integers, and can be directly modulo, SG (x) = x% (m + 1);

2. Alternatively any number of steps of the step, SG (x) = x;

3. Optional step number as the number of a series of discrete, calculation of the template.
 

Proof of principle part may refer to: https://blog.csdn.net/strangedbly/article/details/51137432

 

Third, examples: 

1. S-Nim:http://acm.hdu.edu.cn/showproblem.php?pid=1536

Title templates for each data update about the f [i] can be.

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>

using namespace std;

const int N=100+5;
const int M=1e4+5;

int numOfF, f[N];
int m, l;
int re;


int sg[M];
bool s[M];  //注意此处要为bool类型,int类型会超时
void getSG(int numF,int n)
{
    memset(sg,0,sizeof(sg));
    for(int i=1;i<=n;i++)
    {
        memset(s,0,sizeof(s));
        for(int j=1;f[j]<=i && j<=numF;j++)
        {
            s[sg[i-f[j]]]=1;
        }
        for(int j=0;;j++)
        {
            if(s[j]==0)
            {
                sg[i]=j;
                break;
            }
        }
    }
}

int main()
{
    while(scanf("%d",&numOfF)!=-1)
    {
        if(numOfF==0) break;
        for(int i=1;i<=numOfF;i++) scanf("%d",&f[i]);
        sort(f+1, f+1+numOfF);
        getSG(numOfF, M);
        scanf("%d",&m);
        for(int i=1;i<=m;i++)
        {
            scanf("%d",&l);
            int x;
            re=0;
            for(int i=1;i<=l;i++)
            {
                scanf("%d",&x);
                re^=sg[x];
            }
            if(re==0) printf("L");    //P-position
            else printf("W");
        }
        printf("\n");
    }
}

2. Northcott Game:http://acm.hdu.edu.cn/showproblem.php?pid=1730

The distance between the two pieces as a pile of stones to look, it can be seen when the distance between the two pieces is 0 is P-position.

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>

using namespace std;

int main()
{
    int n,m;
    int x,y;
    int p,re;
    while(scanf("%d%d",&n,&m)!=-1)
    {
        re=0;
        for(int i=1;i<=n;i++)
        {
            scanf("%d%d",&x,&y);
            p=abs(x-y)-1;
            re^=p;
        }
        if(re==0) printf("BAD LUCK!\n");    //P-position
        else printf("I WIN!\n");
    }
}

3.  Fibonacci again and again:http://acm.hdu.edu.cn/showproblem.php?pid=1848

Calculation or directly give F [] value, applied to the template.

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>

using namespace std;

const int N=1e3+5;

int a[5];
int f[16]={1,1,2,3,5,8,13,21,34,55,89,144,233,377,610,987};

bool s[N];
int sg[N];
void getSG(int numF,int n)
{
    memset(sg,0,sizeof(sg));
    for(int i=1;i<=n;i++)
    {
        memset(s,0,sizeof(s));
        for(int j=1;f[j]<=i && j<=numF;j++)
            s[sg[i-f[j]]]=1;
        for(int j=0;j<=n;j++)
        {
            if(s[j]==0)
            {
                sg[i]=j;
                break;
            }
        }
    }
}

int main()
{
    getSG(15, N);
    int re;
    while(scanf("%d%d%d",&a[0],&a[1],&a[2])!=-1)
    {
        re=0;
        if(a[0]+a[1]+a[2]==0) break;
        re^=sg[a[0]]^sg[a[1]]^sg[a[2]];
        if(re==0) printf("Nacci\n");    //P-position
        else printf("Fibo\n");
    }
}

4.  Rabbit and Grass:http://acm.hdu.edu.cn/showproblem.php?pid=1849

Put each piece can be seen as a pile of stones.

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>

using namespace std;

int main()
{
    int m;
    while(scanf("%d",&m)!=-1)
    {
        if(m==0) break;
        int x;
        int re=0;
        while(m--)
        {
            scanf("%d",&x);
            re^=x;
        }
        if(re==0) printf("Grass Win!\n");    //P-positon
        else printf("Rabbit Win!\n");
    }
}

5.  John:http://acm.hdu.edu.cn/showproblem.php?pid=1907

Anti Nimes Game template title.

#include <iostream>
#include <stdio.h>

using namespace std;

int main()
{
    int t;
    int n;
    cin>>t;
    while(t--)
    {
        scanf("%d",&n);
        int flag=0;
        int re=0;
        while(n--)
        {
            int x;
            scanf("%d",&x);
            if(x>1) flag=1;
            re^=x;
        }
        if(re==0 && flag==0 || re!=0 && flag==1)
            printf("John\n");   //N-position
        else
            printf("Brother\n");

    }
}

6.  Be the Winner​​​​​​​:http://acm.hdu.edu.cn/showproblem.php?pid=2509

Anti Nimes Game.

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>

using namespace std;

int main()
{
    int n;
    while(scanf("%d",&n)!=-1)
    {
        int x;
        int re=0;
        int flag=0;
        while(n--)
        {
            scanf("%d",&x);
            if(x>1) flag=1;
            re^=x;
        }
        if(re==0 && flag==0 || re!=0 && flag==1)
        {
            printf("Yes\n");
        }
        else printf("No\n");
    }
}

7. Digital Deletions:http://acm.hdu.edu.cn/showproblem.php?pid=1404

Violence all the N-position according to the nature of the above-described P-position and the N-position.

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <math.h>

using namespace std;

const int N=1e6+5;

char s[10];

bool sg[N];

int getLen(int x)
{
    for(int i=6;i>=1;i--)
    {
        int p=pow(10,i-1);
        if(x/p) return i;
    }
}

void getSG(int x)
{
    int len=getLen(x);
    for(int i=1;i<=len;i++)
    {
        int p=pow(10,i-1);
        int w=x/p%10;
        int s=x;
        for(int j=w;j<9;j++)   //该位0-9都是N-position
        {
            s+=p;
            if(s<1e6) sg[s]=1;
        }
    }

    int s=x,p=1;
    while(len<6)    //位数小于6直接抹0达到 N-position
    {
        s*=10;
        for(int i=0;i<p;i++)
        {
            if(s+i<1e6) sg[s+i]=1;
        }
        p*=10;
        len++;
    }
}



int main()
{
    memset(sg,0,sizeof(sg));
    sg[0]=1;    //N-position
    for(int i=1;i<1e6;i++)
    {
        if(sg[i]==0) getSG(i);  //P-position
    }
    while(gets(s))
    {
        if(s[0]=='0') printf("Yes\n");
        else
        {
            int num=atoi(s);
            if(sg[num]!=0) printf("Yes\n"); //N-position
            else printf("No\n");
        }
    }
}

8.  Bomb Game​​​​​​​:http://acm.hdu.edu.cn/showproblem.php?pid=2873

Dimensional SG, sg after the bomb exploded two bombs can be seen as sg newly generated XOR.

Followed by the top left corner of the board sg [0] [0] = 0, the border of the known sg [i] [0] = sg [0] [i] = i.

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>

using namespace std;

int sg[55][55];
bool s[3000];

int getSG(int x,int y)
{
    memset(s,0,sizeof(s));
    for(int i=0;i<x;i++)
    {
        for(int j=0;j<y;j++)
        {
            s[sg[x][j]^sg[i][y]]=1;
        }
    }
    for(int i=0;;i++)
    {
        if(s[i]==0)
        {
            return i;
        }
    }
}

void SG()
{
    for(int i=0;i<55;i++)
    {
        sg[i][0]=sg[0][i]=i;
    }
    for(int i=1;i<55;i++)
    {
        for(int j=1;j<55;j++)
        {
            sg[i][j]=getSG(i,j);
        }
    }
}

int main()
{
    SG();
    int n,m;
    char in[55][55];
    while(scanf("%d%d",&n,&m)!=-1)
    {
        if(n==0 && m==0) break;
        int re=0;
        for(int i=0;i<n;i++)
        {
            scanf("%s",in[i]);
            for(int j=0;j<m;j++)
                if(in[i][j]=='#')
                re^=sg[i][j];
        }
        if(re!=0) printf("John\n");   //N-position
        else printf("Jack\n");
    }
}

 

Published 34 original articles · won praise 26 · views 10000 +

Guess you like

Origin blog.csdn.net/sinat_40471574/article/details/100051563