刘汝佳《训练指南》上的博弈例题
用到了组合游戏和的概念
#include <cstdio> #include <cstring> typedef long long ll; using namespace std; int sg[210],len; char s[210]; bool ok[210],can[210]; void init(){ bool vis[210]; int i,j; memset(sg,0,sizeof(sg)); sg[0]=0,sg[1]=1,sg[2]=1,sg[3]=1; for(i=4;i<=200;i++){ memset(vis,0,sizeof(vis)); for(j=3;j<=5 && j<=i;j++) vis[sg[i-j]]=1; for(j=1;j+5<=i;j++) vis[sg[j]^sg[i-j-5]]=1; for(j=0;;j++) if(vis[j]==0)break; sg[i]=j; } } bool solve(){ int i,j; bool flag=0,first; for(i=0;i<len;i++){ if(s[i]=='X'){ if(i<len-1 && i>=1 && s[i-1]=='X'){ if(flag==0){ printf("WINNING\n"); flag=1; first=1; } if(first==1){ printf("%d",i+2); first=0; } else printf(" %d",i+2); } if(i<len-1 && i>=1 && s[i+1]=='X'){ if(flag==0){ printf("WINNING\n"); flag=1; first=1; } if(first==1){ printf("%d",i); first=0; } else printf(" %d",i); } if(i>=2 && s[i-2]=='X'){ if(flag==0){ printf("WINNING\n"); flag=1; first=1; } if(first==1){ printf("%d",i); first=0; } else printf(" %d",i); } } } if(flag){ puts(""); return 1; } return 0; } int getans(bool * ok){ int cou=0,i,ans=0; for(i=0;i<len;i++){ if(ok[i]) cou++; else if(ok[i]==0){ ans^=sg[cou]; cou=0; } } ans^=sg[cou]; //这里不要忘了 return ans; } int main(){ int t,T,i,j,ans; init(); scanf("%d",&T); for(t=1;t<=T;t++){ scanf("%s",s); len=strlen(s); bool flag=solve(); if(flag==0){ for(i=0;i<len;i++) ok[i]=1; for(i=0;i<len;i++) if(s[i]=='X') for(j=i-2;j<=i+2;j++) if(j>=0 && j<len) ok[j]=0; ans=getans(ok); if(ans==0) printf("LOSING\n\n"); else{ printf("WINNING\n"); bool first=1; for(i=0;i<len;i++){ if(ok[i]){ for(j=0;j<len;j++) can[j]=ok[j]; for(j=i-2;j<=i+2;j++) if(j>=0 && j<len) can[j]=0; ans=getans(can); if(ans==0){ if(first==1){ printf("%d",i+1); first=0; } else printf(" %d",i+1); } } } puts(""); } } } }