• UVA10561 Treblecross


    Treblecross

     题目大意:给定一个带有.和X的字符串作为初始局面,两人轮流游戏,将.修改为X,当一个人放下X后,出现三个连续的X,游戏接触,放下X的人获胜。判断先手必胜还是必败,并给出第一步到达必胜局面的所有放法。

    对于X.X或..XX..的情况:特殊判断有解并输出即可

    其他情况:每个X旁边都有四个禁区(左右各两个),禁区用i表示,即..iiXii...,显然放到i这个地方是先手必败的

    把整张图的禁区全部标记出来,问题变成了往没被标记的区域放X,没放一个X将有iiXii中的i被标记,被标记的格子不能走,问先手必胜/必败

    每一段没被标记的区域都是一个子游戏,sg[i]表示长度为i的子游戏sg值

    预处理即可

    方案只需要枚举第一步走到哪里,重新判断该局面的SG函数是否为0即可

    被空格和换行各种卡PE或WA。。

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <cstdlib>
      5 #include <algorithm>
      6 #include <queue>
      7 #include <vector>
      8 #include <cmath> 
      9 #define min(a, b) ((a) < (b) ? (a) : (b))
     10 #define max(a, b) ((a) > (b) ? (a) : (b))
     11 #define abs(a) ((a) < 0 ? (-1 * (a)) : (a))
     12 inline void swap(int &a, int &b)
     13 {
     14     int tmp = a;a = b;b = tmp;
     15 }
     16 inline void read(int &x)
     17 {
     18     x = 0;char ch = getchar(), c = ch;
     19     while(ch < '0' || ch > '9') c = ch, ch = getchar();
     20     while(ch <= '9' && ch >= '0') x = x * 10 + ch - '0', ch = getchar();
     21     if(c == '-') x = -x;
     22 }
     23 const int INF = 0x3f3f3f3f;
     24 const int MAXN = 1000;
     25 int t,sg[MAXN + 10],n,b[MAXN + 10],x[MAXN + 10],tot;
     26 char s[MAXN + 10];
     27 void make_sg()
     28 {
     29     sg[0] = 0;sg[1] = sg[2] = sg[3] = 1;
     30     for(register int i = 4;i <= MAXN;++ i) 
     31     {
     32         memset(b, 0, sizeof(b));
     33         for(register int j = 3;j <= i;++ j)
     34             b[sg[max(0, j - 5)] ^ sg[max(i - j, 0)]] = 1;
     35         for(register int j = 0;j <= i;++ j)
     36             if(!b[j])
     37             {
     38                 sg[i] = j;
     39                 break;
     40             }
     41     }
     42 }
     43 //检验特殊情况 
     44 bool check()
     45 {
     46     //单独处理x坐标 
     47     memset(b, 0, sizeof(b));
     48     tot = 0;
     49     for(register int i = 1;i <= n;++ i) if(s[i] == 'X') x[++tot] = i;
     50     int flag = 0;
     51     for(register int i = 2;i <= tot;++ i)
     52         if(x[i] == x[i - 1] + 1)
     53         {
     54             if(x[i] >= 3) b[x[i] - 2] = 1;
     55             b[x[i] + 1] = 1, flag = 1;
     56         }
     57         else if(x[i] == x[i - 1] + 2) 
     58             b[x[i] - 1] = 1, flag = 1;
     59     if(flag)
     60     {
     61         printf("WINNING
    ");
     62         int pre = -1;
     63         for(register int i = 1;i <= n;++ i) 
     64         {
     65             if(b[i])
     66             {
     67                 if(pre != -1) printf("%d ", pre);
     68                 pre = i;
     69             }
     70         }
     71         if(pre != -1) printf("%d", pre);
     72         putchar('
    ');
     73         return 1;
     74     }
     75     return 0; 
     76 } 
     77 int main()
     78 {
     79     read(t);make_sg();
     80     for(;t;--t)
     81     {
     82         scanf("%s", s + 1);n = strlen(s + 1);
     83         int sum = 0;
     84         if(check())
     85             continue;
     86         int l = 0;
     87         for(register int i = 1;i <= tot;++ i)
     88         {
     89             if(x[i] - 3 - l >= 0) sum ^= sg[x[i] - 3 - l];
     90             l = x[i] + 2;
     91         }
     92         if(n - l >= 0) sum ^= sg[n - l];
     93         if(!sum)
     94         {
     95             printf("LOSING
    
    ");
     96             continue;
     97         }
     98         printf("WINNING
    ");
     99         memset(b, 0, sizeof(b));
    100         for(register int i = 1;i <= tot;++ i)
    101         {
    102             if(x[i] - 1 > 0) b[x[i] - 1] = 1;
    103             if(x[i] - 2 > 0) b[x[i] - 2] = 1;
    104             b[x[i]] = b[x[i] + 1] = b[x[i] + 2] = 1; 
    105         }
    106         int pre = -1;
    107         for(register int i = 1;i <= n;++ i)
    108         {
    109             if(b[i]) continue;
    110             //在i这个位置放X
    111             if(i - 1 > 0) ++ b[i - 1];
    112             if(i - 2 > 0) ++ b[i - 2];
    113             ++ b[i]; ++ b[i + 1]; ++ b[i + 2];
    114              
    115             int nsum = 0;
    116             int l = 0;
    117             b[n + 1] = 1;
    118             for(register int j = 1;j <= n + 1;++ j)
    119             {
    120                 if(!b[j] && !l) l = j;
    121                 else if(b[j] && l) nsum ^= sg[j - l], l = 0;
    122             }
    123             if(!nsum)
    124             {
    125                 if(pre != -1) 
    126                     printf("%d ", pre);
    127                 pre = i;
    128             }
    129             if(i - 1 > 0) -- b[i - 1];
    130             if(i - 2 > 0) -- b[i - 2];
    131             -- b[i]; -- b[i + 1]; -- b[i + 2];
    132         }
    133         if(pre != -1) printf("%d", pre);
    134         putchar('
    ');
    135     }
    136     return 0;
    137 } 
    UVA10561
  • 相关阅读:
    Python 生产者与消费者模型
    Python 进程队列
    Python 进程
    Python Socket网络编程
    Python 异常处理
    C# .net 下载了个.dll的文件,怎么用啊?
    ScriptManager.RegisterStartupScript用法详解
    ScriptManager.RegisterStartupScript与ClientScript.RegisterStartupScript区别
    IDisposable接口
    Guid排序问题
  • 原文地址:https://www.cnblogs.com/huibixiaoxing/p/8310558.html
Copyright © 2020-2023  润新知