标签:
题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=32209
【思路】
博弈论。
根据X分布划分禁区,每个可以放置的块为单独一个游戏。按长度定义状态,构造sg函数。依次试验每一种放法。
【代码】
1 #include<cstdio> 2 #include<vector> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 7 const int N = 200+10; 8 9 int g[N],n; 10 11 int mex(vector<int>& s) { 12 if(s.empty()) return 0; 13 sort(s.begin(),s.end()); 14 if(s[0]) return 0; 15 for(int i=1;i<s.size();i++) 16 if(s[i]>s[i-1]+1) return s[i-1]+1; 17 return s[s.size()-1]+1; 18 } 19 void get_g() { 20 g[0]=0; g[1]=g[2]=g[3]=1; 21 for(int i=4;i<=N-10;i++) { 22 vector<int> s; 23 s.push_back(g[i-3]); 24 s.push_back(g[i-4]); 25 if(i>=5) s.push_back(g[i-5]); 26 for(int j=3;j<i-3;j++) 27 s.push_back(g[j-2] ^ g[i-j-3]); 28 g[i]=mex(s); 29 } 30 } 31 32 bool winning(char *s) { 33 int n=strlen(s); 34 for(int i=0;i<n-2;i++) 35 if(s[i]==‘X‘ && s[i+1]==‘X‘ && s[i+2]==‘X‘) return false; 36 int no[N]; 37 memset(no,0,sizeof(no)); 38 no[n]=1; 39 for(int i=0;i<n;i++) if(s[i]==‘X‘) { 40 for(int d=-2;d<=2;d++) 41 if(i+d>=0 && i+d<n) { 42 if(d!=0 && s[i+d]==‘X‘) return true; 43 no[i+d]=1; 44 } 45 } 46 47 int sg=0; 48 int start=-1; 49 for(int i=0;i<=n;i++) { 50 if(start<0 && !no[i]) start=i; 51 if(no[i] && start>=0) sg^=g[i-start]; 52 if(no[i]) start=-1; 53 } 54 return sg!=0; 55 } 56 57 int main() { 58 get_g(); 59 int T; scanf("%d",&T); 60 while(T--) { 61 char s[N]; 62 scanf("%s",s); 63 int n=strlen(s); 64 if(!winning(s)) puts("LOSING\n"); 65 else { 66 puts("WINNING"); 67 bool first=1; 68 for(int i=0;i<n;i++) if(s[i]==‘.‘) { 69 s[i]=‘X‘; 70 if(!winning(s)) 71 if(first) printf("%d",i+1) , first=0; 72 else printf(" %d",i+1); 73 s[i]=‘.‘; 74 } 75 putchar(‘\n‘); 76 } 77 } 78 return 0; 79 }
标签:
原文地址:http://www.cnblogs.com/lidaxin/p/5167428.html