博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
UVA10561 Treblecross
阅读量:4310 次
发布时间:2019-06-06

本文共 3428 字,大约阅读时间需要 11 分钟。

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 
2 #include
3 #include
4 #include
5 #include
6 #include
7 #include
8 #include
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这个位置放X111 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

你可能感兴趣的文章
Nginx配置文件nginx.conf中文详解(总结)
查看>>
Mysql出现Table 'performance_schema.session_status' doesn't exist
查看>>
MySQL innert join、left join、right join等理解
查看>>
vivado模块封装ip/edf
查看>>
sdc时序约束
查看>>
Xilinx Jtag Access/svf文件/BSCANE2
查看>>
NoC片上网络
查看>>
开源SoC整理
查看>>
【2020-3-21】Mac安装Homebrew慢,解决办法
查看>>
influxdb 命令行输出时间为 yyyy-MM-dd HH:mm:ss(年月日时分秒)的方法
查看>>
已知子网掩码,确定ip地址范围
查看>>
判断时间或者数字是否连续
查看>>
docker-daemon.json各配置详解
查看>>
Docker(一)使用阿里云容器镜像服务
查看>>
Docker(三) 构建镜像
查看>>
FFmpeg 是如何实现多态的?
查看>>
FFmpeg 源码分析 - avcodec_send_packet 和 avcodec_receive_frame
查看>>
FFmpeg 新旧版本编码 API 的区别
查看>>
RecyclerView 源码深入解析——绘制流程、缓存机制、动画等
查看>>
Android 面试题整理总结(一)Java 基础
查看>>