UVA 10561 Treblecross(组合游戏_SG定理的应用)

来源:互联网 发布:寸步优游知远近下联 编辑:程序博客网 时间:2024/06/08 06:58

题目地址

例题 ,强大的SG定理。。SG != 0 -----win   ;    SG == 0 -----lose ;

SG的计算:

单个游戏:  SG = mex ( S )   ,  S是所有后继态(可能是单个游戏,也可能是组合游戏)的SG函数值集合。

组合游戏:  各子游戏SG值的亦或值

参考代码:

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <vector>using namespace std;const int maxn = 300;char s[maxn];int N;vector<int>pos;int g[maxn] , a[maxn],b[maxn] , M;int isx[maxn];int mex(vector<int>& S){    sort(S.begin() , S.end());    if(S[0]) return 0;    int sz=S.size();    for(int i=1;i<sz ;i++){        if(S[i]>S[i-1]+1) return S[i-1]+1;    }    return S[S.size()-1]+1;}int G(int x){    if(g[x]!=-1) return g[x];    if(x==0) return g[x]=0;    if(x==1 || x==2 || x==3 ) return g[x] = 1;    vector<int>S;    if(x>=3) S.push_back(G(x-3));    if(x>=4) S.push_back(G(x-4));    if(x>=5) S.push_back(G(x-5));    if(x>5) {        for(int i=1;i+5<=x;i++){            S.push_back(G(i) ^ G(x-i-5));        }    }    return g[x] = mex(S);}void update(int p){    if(p-1>=1)  s[p-1] = 'X';    if(p-2>=1)  s[p-2] = 'X';    if(p+1<=N)  s[p+1] = 'X';    if(p+2<=N)  s[p+2] = 'X';}bool check(){    pos.clear();    for(int i=1;i<=N;i++) if(s[i]=='.') {        if(i-2>=1){            if(s[i-2]=='X' && s[i-1]=='X'){                pos.push_back(i);                continue;            }        }        if(i-1>=1 && i+1<=N){            if(s[i-1]=='X' && s[i+1]=='X'){                pos.push_back(i);                continue;            }        }        if(i+2<=N){            if(s[i+1]=='X' && s[i+2]=='X'){                pos.push_back(i);                continue;            }        }    }    return pos.size() > 0;}int main(){    freopen("input.txt","r",stdin);    memset(g,-1,sizeof(g));    int TT;    scanf("%d",&TT);    while(TT--){        scanf("%s",s+1);        N = strlen(s+1);        memset(isx,0,sizeof(isx));        for(int i=1;i<=N;i++)            if(s[i]=='X') isx[i]=1;        if(check()){            printf("WINNING\n");            printf("%d",pos[0]);            int sz = pos.size();            for(int i=1;i<sz; i++)                printf(" %d",pos[i]);            printf("\n");            continue;        }        int nim = 0;        M = 0;        for(int i=1;i<=N;i++)            if(isx[i]) update(i);        for(int i=1;i<=N;i++){            if(s[i]=='.'){                a[M] = i;                while(s[i+1]=='.') i++;                b[M++] = i;            }        }        for(int i=0;i<M;i++)            nim ^= G( b[i] - a[i] + 1 );        if(nim){            printf("WINNING\n");            for(int i=0;i<M;i++){                int v = nim^G((b[i]-a[i]+1));                for(int t=a[i] ; t<=b[i] ;t++){                    int sg = v;                    if(t-a[i]>=2) sg^=G(t-a[i]-2);                    if(b[i]-t>=2) sg^=G(b[i]-t-2);                    if(sg==0) pos.push_back(t);                }            }            printf("%d",pos[0]);            int sz = pos.size();            for(int i=1;i<sz; i++)                printf(" %d",pos[i]);            printf("\n");        }        else {            printf("LOSING\n");            printf("\n");        }    }    return 0;}