poj 2960 S-Nim (SG)

题意:

K个数,s1...sk。

m个状态,对于某一个状态,有L堆石子,每人每次取的石子个数只能是s1...sk的一个,且只能在一堆中取。

输出m个状态是先手胜还是先手败,先手胜输出W,否则输出L。

输入格式及数据范围:

For each test case: The first line contains a number k (0 < k ≤ 100) describing the size of S, followed by k numbers si (0 < si ≤ 10000) describing S. The second line contains a number m (0 < m ≤ 100) describing the number of positions to evaluate. The next m lines each contain a number l (0 < l ≤ 100) describing the number of heaps and l numbers hi (0 ≤ hi ≤ 10000) describing the number of beads in the heaps. 
The last test case is followed by a 0 on a line of its own.

思路:

对于每个小堆求sg1...sgL(用记忆搜),则某个状态的SG=sg1^...^sgL。 SG概念题。

代码:

int sg[10005];
int k,m,l;
int s[105];
char ss[105];

void dfs(int x){
    bool vis[10005] = {0};

    if(sg[x]!=-1)
        return;

    rep(i,1,k){
        if(x>=s[i]){
            if(sg[x-s[i]]==-1) dfs(x-s[i]);
            vis[sg[x-s[i]]] = true;
        }
    }
    for(int i=0;;++i){
        if(!vis[i]){
            sg[x]=i;
            return;
        }
    }
}

int main(){
    int x;

    while(scanf("%d",&k),k){
        rep(i,1,k) scanf("%d",&s[i]);
        mem(sg,-1); sg[0]=0;

        scanf("%d",&m);
        int geshu=0;
        while(m--){
            scanf("%d",&l);
            int ans=0;
            rep(i,1,l){
                scanf("%d",&x);
                if(sg[x]==-1) dfs(x);
                ans=ans^sg[x];
            }
            if(!ans)
                ss[++geshu]='L';
            else
                ss[++geshu]='W';
        }
        rep(i,1,geshu) printf("%c",ss[i]); cout<<endl;
    }
}
原文地址:https://www.cnblogs.com/fish7/p/4004676.html