• UVA 10561 Treblecross(博弈论)


    题目链接: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
    ");
    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('
    ');
    76         }
    77     }
    78     return 0;
    79 }
  • 相关阅读:
    树状数组BIT
    KMP算法习题(一本通)
    西大附中集训日志
    图论大杂汇
    [IOI2008/BZOJ1791 岛屿](处理基环树的小技巧&基于bfs树形DP)
    字符串知识清单
    BZOJ刷题列表【转载于hzwer】
    NOIP2018复赛游记
    求极大子矩阵的两种方法
    NOIP2002-字串变换【双向BFS】
  • 原文地址:https://www.cnblogs.com/lidaxin/p/5167428.html
Copyright © 2020-2023  润新知