ZOJ 3666 博弈 SG函数

SG函数:

对于任意状态,定义SG(x)=mex(S),其中S是x的后继状态的SG函数值集合,mex(S)表示不再S内的最小非负整数

SG(X)=0当且仅当x为必败态。

解:

构造一个有向无环图(树),SG(x)=mex(SG(y)) y为x的孩子节点。

SG(所有叶子节点)=0

#include <stdio.h> 
#include <algorithm>
#include <string.h>
#include <vector>
using namespace std;
#define MAXN    10005
int n;
int sg[MAXN]; 
vector <int >map[MAXN];
int vis[MAXN];
void dfs(int y)
{
    if (vis[y]) return;
    int i,j;
    int x;
    vector<int> tmp;
        for (j=0;j<map[y].size();j++)
        {
            dfs(map[y][j]);
            tmp.push_back(sg[map[y][j]]);
        }
        sort(tmp.begin(),tmp.end());
        x=0;
        int flag=true;
        for (i=0;i<tmp.size();i++)
            if (tmp[i]==x)
                x++;
            else
            {
                if (tmp[i]>x)
                {
                    break;
                }
            }
        sg[y]=x;
        vis[y]=1;
}
int main() 
{    
    int i,j,m,x;
    int dot[MAXN];
    int cas=1;
    while (scanf("%d",&n)!=EOF)
    {
        printf("Case %d:
",cas++);
        for (i=1;i<=n;i++)
            map[i].clear();
        memset(sg,0,sizeof(sg));
        memset(vis,0,sizeof(vis));
        for (i=1;i<n;i++)
        {
            scanf("%d",&dot[i]);
            for (j=0;j<dot[i];j++)
            {
                scanf("%d",&x);
                map[i].push_back(x);
            }
        }
        sg[n]=0;
        for (i=1;i<=n;i++)
            if (!vis[i])
                dfs(i);
        int q;
        int p;
        scanf("%d",&q);
        for (i=0;i<q;i++)
        {
            scanf("%d",&p);
            int ans=0;
            for (j=0;j<p;j++)
            {
                scanf("%d",&x);
                ans^=sg[x];
            }
            if (ans==0)
                printf("Bob
");
            else
                printf("Alice
");
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/six-god/p/3748829.html