uva10561(SG)

题目连接:https://vjudge.net/problem/UVA-10561

抄的别人的代码,大概能理解,自己写还很费劲,再练习。。。。

参考:http://www.cnblogs.com/cyb123456/p/5815570.html

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 using namespace std;
  5 
  6 const int maxn=210;
  7 int t,res[maxn],way,len,sg[maxn];
  8 char s[maxn];
  9 
 10 int check()
 11 {
 12     for(int i=0;i<len-2;i++)
 13         if(s[i]=='X'&&s[i+1]=='X'&&s[i+2]=='X')
 14         return 1;
 15     return 0;
 16 }
 17 
 18 //记忆化求sg
 19 int SG(int x)
 20 {
 21     int vis[maxn];
 22     int t;
 23     if(sg[x]!=-1) return sg[x];
 24     if(x==0) return sg[x]=0; //终态,先手必败
 25     memset(vis,0,sizeof(vis));
 26     for(int i=1;i<=x;i++)
 27     {
 28         int t=SG(max(0,i-3))^SG(max(0,x-i-2));
 29         vis[t]=1;
 30     }
 31     for(int i=0;;i++)
 32     {
 33         if(!vis[i]) return sg[x]=i;
 34     }
 35 }
 36 
 37 //当前状态是否可行
 38 int getres()
 39 {
 40     for(int i=0;i<len;i++)
 41     {
 42         if(s[i]=='.')
 43         {
 44             s[i]='X';
 45             if(check())  //后手必胜?
 46             {
 47                 s[i]='.';
 48                 return 0; //先手要避免这种情况留给对手
 49             }
 50              s[i]='.';
 51         }
 52     }
 53     int ans=0,num=0;
 54     for(int i=0;i<len;i++)
 55     {
 56         //如果到禁区
 57         if(s[i]=='X'||(i>=1&&s[i-1]=='X')||(i>=2&&s[i-2]=='X')
 58             ||(i+1<len&&s[i+1]=='X')||(i+2<len&&s[i+2]=='X'))
 59         {
 60             ans^=SG(num);
 61             num=0;
 62         }
 63         else num++;
 64     }
 65     ans^=SG(num);
 66     return ans==0;
 67 }
 68 
 69 void solve()
 70 
 71 {
 72     way=0;
 73     len=strlen(s);
 74     for(int i=0;i<len;i++)
 75     {
 76         if(s[i]!='.') continue;
 77         s[i]='X';
 78         if(check()||getres())
 79             res[way++]=i+1;  //先手放x的位置(下标+1)
 80         s[i]='.';
 81     }
 82 }
 83 int main()
 84 {
 85     memset(sg,-1,sizeof(sg));
 86     scanf("%d",&t);
 87     while(t--)
 88     {
 89         scanf("%s",s);
 90         solve();
 91         if(way==0) puts("LOSING\n");
 92         else
 93         {
 94             printf("WINNING\n%d",res[0]);
 95             for(int i=1;i<way;i++) printf(" %d",res[i]);
 96             puts("");
 97         }
 98     }
 99     return 0;
100 }

 

posted @ 2017-04-19 20:58  yijiull  阅读(144)  评论(0编辑  收藏  举报