UVa 10561 (SG函数 递推) Treblecross
2015-03-10 15:06
435 查看
如果已经有三个相邻的X,则先手已经输了。
如果有两个相邻的X或者两个X相隔一个.,那么先手一定胜。
除去上面两种情况,每个X周围两个格子不能再放X了,因为放完之后,队手下一轮再放一个就输了。
最后当“禁区”布满整行,不能再放X了,那个人就输了。
每放一个X,禁区会把它所在的线段“分割”开来,这若干个片段就可以看做若干个游戏的和。
设g(x)表示x个连续格子对应的SG函数值,递推来求g(x):
g(x) = mex{ g(x-3), g(x-4), g(x-5), g(x-6) xor g(1), g(x-7) xor g(2)... }
g(0) = 0, g(1) = g(2) = g(3) = 1
枚举策略时,就是模拟下一步的状态,记录其中所有必败状态。
代码君
如果有两个相邻的X或者两个X相隔一个.,那么先手一定胜。
除去上面两种情况,每个X周围两个格子不能再放X了,因为放完之后,队手下一轮再放一个就输了。
最后当“禁区”布满整行,不能再放X了,那个人就输了。
每放一个X,禁区会把它所在的线段“分割”开来,这若干个片段就可以看做若干个游戏的和。
设g(x)表示x个连续格子对应的SG函数值,递推来求g(x):
g(x) = mex{ g(x-3), g(x-4), g(x-5), g(x-6) xor g(1), g(x-7) xor g(2)... }
g(0) = 0, g(1) = g(2) = g(3) = 1
枚举策略时,就是模拟下一步的状态,记录其中所有必败状态。
#include <cstdio> #include <cstring> const int maxn = 200; char s[maxn + 10]; int g[maxn + 10], ans[maxn + 10]; bool vis[maxn + 10]; bool winning(const char* s) { int n = strlen(s); for(int i = 0; i < n-2; i++)//已经有三个相邻的X,先手输 if(s[i] == 'X' && s[i+1] == 'X' && s[i+2] == 'X') return false; bool no[n+1]; memset(no, false, sizeof(no)); for(int i = 0; i < n; i++) if(s[i] == 'X') { for(int d = -2; d <= 2; d++) { if(i+d >= 0 && i+d < n) { if(d != 0 && s[i+d] == 'X') return true;//有两个X在彼此的禁区,先手胜 no[i+d] = true;//设置禁区 } } } no = 1; int sg = 0; for(int i = 0; i < n; i++) { if(no[i]) continue; int cnt = 0; while(i < n && !no[i]) { i++; cnt++; } sg ^= g[cnt]; } return sg != 0; } int main() { //freopen("in.txt", "r", stdin); g[0] = 0; g[1] = g[2] = g[3] = 1; for(int i = 4; i <= maxn; i++) {//递推求函数g memset(vis, false, sizeof(vis)); for(int j = 3; i-j >= 0; j++) { int v = 0; v ^= g[i-j]; int x = j - 5; if(x > 0) v ^= g[x]; vis[v] = true; for(int j = 0; ; j++) if(!vis[j]) { g[i] = j; break; } } } int T; scanf("%d", &T); while(T--) { scanf("%s", s); if(!winning(s)) { printf("LOSING\n\n"); continue; } puts("WINNING"); int n = strlen(s); memset(ans, 0, sizeof(ans)); int p = 0; for(int i = 0; i < n; i++) if(s[i] == '.') { s[i] = 'X'; if(!winning(s)) ans[p++] = i+1;//后继必败状态便是先手下一步的策略 s[i] = '.'; } for(int i = 0; i < p; i++) { if(i) printf(" "); printf("%d", ans[i]); } printf("\n"); } return 0; }
代码君
相关文章推荐
- 【UVA 10561】 Treblecross|博弈论|SG函数
- uva 10561 Treblecross (SG函数)
- UVa 10561 Treblecross (SG函数)
- UVA - 10561 Treblecross (博弈数学&SG函数)
- UVA 10561 - Treblecross(博弈SG函数)
- UVA 10561 - Treblecross(博弈SG函数)
- UVA 10561 Treblecross 组合游戏/SG定理
- uva 10561 - Treblecross(Nim)
- UVA - 10561 Treblecross (SG定理)
- uva 10561 Treblecross(博弈)
- uva10561 - Treblecross
- [UVa 10561]Treblecross游戏
- UVA 10561 Treblecross
- uva10561 - Treblecross SG定理
- [UVA10561] Treblecross && 博弈 SG函数
- 排列组合,递推(比赛名次,uva 12034)
- uva 11174 - Stand in a Line(逆元+递推)
- uva 12034 Race递推
- UVa11040 - Add bricks in the wall (规律递推)
- [UVA1378] A Funny Stone Game && SG函数