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\n");
 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('\n');
 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\n\n");
 96             continue;
 97         }
 98         printf("WINNING\n");
 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('\n');
135     }
136     return 0;
137 } 

UVA10561

转载于:https://www.cnblogs.com/huibixiaoxing/p/8310558.html

UVA10561 Treblecross相关推荐

  1. mysql建表简单的date数据类型_MySQL建表 TIMESTAMP 类型字段问题

    Android基础测试题(四) 看了前两道题大家有没有发现,测试题少了(一),大家猜猜测试题(一)是什么? Android基础测试题(四): 需求: 建一个方法,格式化输出2016-11-14 10: ...

  2. 《算法入门经典大赛——培训指南》第二章考试

    UVa特别考试 UVa站点专门为本书设立的分类题库配合,方便读者提交: http://uva.onlinejudge.org/index.php?option=com_onlinejudge& ...

  3. 组合游戏(分石子,nim游戏,sg)

    一.最近在学习组合游戏方面的知识,我们可以考虑这类组合游戏: (1)两个人轮流操作 (2)游戏状态有限,总能走到最终状态,且都不会出现以前的状态.即给定初始状态,游戏的胜负是可以预见的. (3)规定谁 ...

  4. 博弈论与 sg 函数

    博弈论 定义 必胜状态 为 先手必胜的状态 , 必败状态 为 先手必败的状态 . 通过推理,我们可以得出下面三条定理: 定理 1:没有后继状态的状态是必败状态. 定理 2:一个状态是必胜状态当且仅当存 ...

最新文章

  1. Ubuntu中的minicom
  2. deepsort原理快速弄懂——时效比最高的
  3. linux图形登陆报拒绝权限,Linux-权限被拒绝?
  4. python计算小数点后有几位_数学提高小数除法竖式计算过程
  5. C++异常 返回错误码
  6. NLP-基础知识-003(词性标注)
  7. 2013年4月20日 通用权限管理系统组件V3.8功能改进说明
  8. 5、Power Map—实例:填充地图
  9. Python实现目录文件的全量和增量备份
  10. Pandas的学习(1.pandas的介绍以及pandas中的Series的创建)
  11. leetcode 227. Basic Calculator II | 227. 基本计算器 II(中缀表达式求值)
  12. matlab不显示变量,Matlab空间面板SAR模型运行时解释变量显示不全
  13. java从数组中删除元素(数组的缩容)
  14. 1044. 火星数字(20)-PAT乙级真题
  15. poj1036-dp
  16. echarts:迁徙图
  17. WIN10和WIN11修改C盘用户文件夹名称
  18. 新型材料集成墙面,到底“新”在哪里?
  19. 爆火出圈的chatGPT
  20. SSO单点登录详解------三、单点注销流程解析

热门文章

  1. SDL 库 无法解析的外部符号 __imp__fprintf
  2. [Labview资料] labview事件结构学习
  3. multiselect多选下拉框
  4. javascript --- 防抖与节流
  5. 吉林省第二条国际铁路联运大通道“长珲欧”启动测试
  6. MySQL的权限分配
  7. scikit-learn点滴
  8. 解决替换weblogic的commons-fileupload.jar后引发的问题
  9. android调用照相机拍照获取照片并做简单剪裁
  10. cocos2d的常用动作及效果总结之五:Animation