题目连接: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 "); 92 else 93 { 94 printf("WINNING %d",res[0]); 95 for(int i=1;i<way;i++) printf(" %d",res[i]); 96 puts(""); 97 } 98 } 99 return 0; 100 }