UVA 10561 - Treblecross(博弈SG函数)
UVA 10561 - Treblecross
题意:给定一个串,上面有'X'和'.',能够在'.'的位置放X。谁先放出3个'X'就赢了,求先手必胜的策略
思路:SG函数,每一个串要是上面有一个X,周围的4个位置就是禁区了(放下去必败)。所以能够以X分为几个子游戏去求SG函数的异或和进行推断。至于求策略。就是枚举每一个位置就能够了
代码:
#include <stdio.h> #include <string.h> #include <algorithm> using namespace std; const int N = 205; int t, out[N], on, len, sg[N]; char str[N]; bool win() { for (int i = 0; i < len - 2; i++) { if (str[i] == 'X' && str[i + 1] == 'X' && str[i + 2] == 'X') return true; } return false; } int mex(int x) { bool vis[N]; int i, t; if (sg[x] != -1) return sg[x]; if (x == 0) return sg[x] = 0; memset(vis, false, sizeof(vis)); for (int i = 1; i <= x; i++) { int t = mex(max(0, i - 3))^mex(max(0, x - i - 2)); vis[t] = true; } for (int i = 0; i < N; i++) { if (vis[i]) continue; return sg[x] = i; } } bool towin() { for (int i = 0; i < len; i++) { if (str[i] == '.') { str[i] = 'X'; if (win()) { str[i] = '.'; return false; } str[i] = '.'; } } int ans = 0, num = 0; for (int i = 0; i < len; i++) { if (str[i] == 'X' || (i >= 1 && str[i - 1] == 'X') || (i >= 2 && str[i - 2] == 'X') || (i + 1 < len && str[i + 1] == 'X') || (i + 2 < len && str[i + 2] == 'X')) { ans ^= mex(num); num = 0; } else num++; } ans ^= mex(num); return ans == 0; } void solve() { on = 0; len = strlen(str); for (int i = 0; i < len; i++) { if (str[i] != '.') continue; str[i] = 'X'; if (win() || towin()) out[on++] = i + 1; str[i] = '.'; } } int main() { memset(sg, -1, sizeof(sg)); scanf("%d", &t); while (t--) { scanf("%s", str); solve(); if (on == 0) printf("LOSING\n\n"); else { printf("WINNING\n%d", out[0]); for (int i = 1; i < on; i++) printf(" %d", out[i]); printf("\n"); } } return 0; }