博弈论--sg函数

博弈论

mex

首先定义mex(minimal excludant)运算,这是施加于一个集合的运算,表示最小的不属于这个集合的非负整数。

例如mex{0,1,2,4}=3、mex{2,3,5}=0、mex{}=0。

sg函数

定义P-position和N-position,其中P代表Previous,N代表Next。

直观的说,先手必败的局面是P-position,先手必胜的局面是N-position,

定义sg(x)=mex{ sg(y) | y是x的子状态 },也就是说y可以由x转移过去。

若x的所有子状态y都是必胜态,那么x就是必败态。

若x的所有子状态y有一个必败态,那么x就是必胜态。

如何求sg函数

打表

#include <bits/stdc++.h>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
#define pii pair<int,int>
#define int long long
const int inf = 0x3f3f3f3f;
const int maxn = 1110;
const int M = 1e9+7;
int n;

int a[maxn];            //每次移动可以选取的值
int sg[maxn];
bool vis[maxn];

void getsg()
{
    for(int i = 1; i <= n; i++) 
    {
        mem(vis,0);
        for(int j = 1; a[j] <= i; j++)         //可以取的值
        {
            vis[sg[i-a[j]]] = 1;            //(i-a[j])状态可达
        }
        int res = 0;
        for(;;res++)
        {
            if(!vis[res]) break;
        }
        sg[i] = res;
    }
}



signed main()
{
    cin>>n;
    sg[0] = 0;      //0表示必败
    for(int i = 1; i <= n; i++) 
    {
        a[i] = i*i;
    }
    getsg();
    for(int i = 1; i <= n; i++) 
    {
        cout<<sg[i]<<' ';
    }
    cout<<endl;
    return 0;
}

dfs

int a[maxn];        //可以取的值

int sg[maxn];

int dfs_sg(int x)
{
    if(sg[x] != -1) return sg[x];
    int i;                  //必须要声明一下
    bool vis[maxn];         //每次dfs对应不同的vis
    mem(vis,0);
    for(int i = 1; i <= n; i++) 
    {
        if(x - a[i] >= 0)
        {
            vis[dfs_sg(x-a[i])] = 1;
        }
    }
    int res = 0;
    for(;;res++)
    {
        if(!vis[res]) break;
    }
    return sg[x] = res;
}

简化版本的sg

bool winnerSquareGame(int n) {
    vector<int> v;
    for(int i = 1; i*i <= n; i++) 
    {
        v.push_back(i*i);
    }
    vector<int> sg(n+1);                  //只有两种值,0或1,0代表必败
    for(int i = 1; i <= n; i++) 
    {
        for(auto j : v)
        {
            if(j <= i)
            {
                if(!sg[i-j])                  //如果子状态有必败,那么我必胜
                {
                    sg[i] = 1;
                    break;
                }
            }
            else break;
        }
    }
    return sg[n];
}
原文地址:https://www.cnblogs.com/hezongdnf/p/12867343.html