http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1502
博弈 SG 不可以使出现 XX 或者 X.X的情况,这样下一个人就赢了
枚举每个.将其变成X 看是否可以让对手输
1,已经出现了 XXX 对手已输
2,如果正好出现了 XX 或者 X.X 对手赢
3,如果一个地方的.变成X 不会出现XX或者X.X 把这些地方分成一个个的段 SG
代码:
#include <iostream> #include <cstdio> #include <string> #include <cstring> #include <cmath> #include <algorithm> #include <queue> #define ll long long #define lint long long using namespace std; const int N=205; int sg[N]; int dp(int x) { if(sg[x]!=-1) return sg[x]; if(x==0) return (sg[x]=0); bool ok[N]; memset(ok,false,sizeof(ok)); for(int i=1;i<=x;++i) { int k=(dp(max(0,i-3))^dp(max(0,x-i-2))); ok[k]=true; } for(int i=0;i<N;++i) if(!ok[i]) {sg[x]=i;break;} return sg[x]; } bool ok(string s) { for(unsigned int i=0;i<s.size()-2;++i) { if(s[i]=='X'&&s[i+1]=='X'&&s[i+2]=='X') return true; } return false; } bool ok1(string s) { for(unsigned int i=0;i<s.size();++i) if(s[i]=='.') { s[i]='X'; if(ok(s)) return false; s[i]='.'; } int nim=0; int tmp=0; for(unsigned int i=0;i<s.size();++i) { if(s[i]=='X'||(i>=1&&s[i-1]=='X')||(i>=2&&s[i-2]=='X')||(i+1<s.size()&&s[i+1]=='X')||(i+2<s.size()&&s[i+2]=='X')) {nim=(nim^dp(tmp));tmp=0;} else ++tmp; } nim=(nim^dp(tmp)); if(nim==0) return true; return false; } void solve(vector<int> &vt,string &s) { for(unsigned int i=0;i<s.size();++i) if(s[i]=='.') { s[i]='X'; if(ok(s)||ok1(s)) vt.push_back(i+1); s[i]='.'; } } int main() { //freopen("data.in","r",stdin); memset(sg,-1,sizeof(sg)); int T; cin>>T; while(T--) { string s; cin>>s; vector<int>vt; solve(vt,s); if(vt.size()==0) cout<<"LOSING"<<endl; else cout<<"WINNING"<<endl; for(unsigned int i=0;i<vt.size();++i) { if(i>0) cout<<" "; cout<<vt[i]; } cout<<endl; } return 0; }