UVa10561 Treblecross

博弈 sg函数

 

如果能一步取胜的话,直接扫一遍,找出所有能一步取胜的位置输出。

否则枚举放‘X’的位置,计算剩下空区间的SG函数的异或和,若为0,则该位置可以作为答案。

计算空区间时要刨去X旁边的两个空(放在这里必败) 例如.X.....X.这一区段的可用长度为3

SG函数的预处理还不太理解


↓那个pd()并没有用到

  1 /*by SilverN*/
  2 #include<iostream>
  3 #include<algorithm>
  4 #include<cstring>
  5 #include<cstdio>
  6 #include<cmath>
  7 using namespace std;
  8 const int mxn=210;
  9 char s[mxn];
 10 int n,f[mxn];
 11 inline bool pd(){
 12     for(int i=2;i<n;i++){
 13         if(s[i-1]=='X' && s[i]=='X' && s[i+1]=='X')return 1;
 14     }
 15     return 0;
 16 }
 17 inline bool check(int pos){
 18     if(s[pos+1]=='X'){
 19         if(s[pos-1]=='X' || s[pos+2]=='X')return 1;
 20     }
 21     else if(s[pos-1]=='X'){
 22         if(pos>2 && s[pos-2]=='X')return 1;
 23     }
 24     return 0;
 25 }
 26 inline bool ar(int p){
 27     for(int i=max(1,p-2);i<=p+2;i++)if(s[i]=='X')return 1;
 28     return 0;
 29 }
 30 bool calc(){
 31     int i,j,len=0;
 32     int res=0;
 33     for(i=1;i<=n;i++){
 34         if(ar(i)){
 35             res^=f[len]; len=0;
 36         }
 37         else len++;
 38     }
 39     res^=f[len];
 40     return res;
 41 }
 42 int ans[mxn],cnt=0;
 43 void solve(){
 44     cnt=0;
 45     int i,j;
 46     for(i=1;i<=n;i++){
 47         if(s[i]!='.')continue;
 48         if(check(i)){
 49             for(j=i;j<=n;j++)
 50                 if(s[j]=='.' && check(j)){ans[++cnt]=j;}
 51             return;
 52         }
 53     }
 54     if(calc()){
 55         for(i=1;i<=n;i++){
 56             if(!ar(i)){
 57                 s[i]='X';
 58                 if(!calc()){
 59                     ans[++cnt]=i;
 60                 }
 61                 s[i]='.';
 62             }
 63         }
 64     }
 65     return;
 66 }
 67 int vis[mxn];
 68 void init(){//处理sg函数 
 69     int i,j,x;
 70     f[1]=f[2]=1;
 71     for(i=3;i<mxn;i++){
 72         memset(vis,0,sizeof vis);
 73         for(j=1;j*2<=i+1;j++){
 74             x=f[i-j-2];//去掉边界两个空位 
 75             if(j>3)x^=f[j-3];
 76             vis[x]=1;
 77         }
 78         for(j=0;;j++){if(!vis[j]){f[i]=j;break;}}
 79     }
 80     return;
 81 }
 82 int main(){
 83     int T;scanf("%d",&T);
 84     init();
 85     while(T--){
 86         memset(s,0,sizeof s);
 87         scanf("%s",s+1);
 88         n=strlen(s+1);
 89         solve();
 90         if(cnt){
 91             printf("WINNING\n");
 92             for(int i=1;i<cnt;i++){
 93                 printf("%d ",ans[i]);
 94             }
 95             printf("%d\n",ans[cnt]);
 96         }
 97         else printf("LOSING\n\n");
 98     }
 99     return 0;
100 }

 

posted @ 2017-01-14 00:36  SilverNebula  阅读(190)  评论(0编辑  收藏  举报
AmazingCounters.com