刘汝佳《训练指南》上的博弈例题
用到了组合游戏和的概念
#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("");
}
}
}
}