第一次写这么复杂的SG函数 Orz 还好记忆化比较好写
输出方案的话就直接枚举第一个X放在哪里
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#define SF scanf
#define PF printf
#define max(a, b) ((a) < (b) ? (b) : (a))
using namespace std;
typedef long long LL;
const int MAXN = 200;
int SG[MAXN+10], Len, CNT, Step[MAXN+10];
char s[MAXN+10];bool Now_Win()
{
for(int i = 0; i < Len - 2; i++)
if(s[i] == 'X' && s[i+1] == 'X' && s[i+2] == 'X')
return true;
return false;
}
int getSG(int x)
{
bool vis[MAXN+10];
if(~SG[x]) return SG[x];
if(x == 0) return SG[x] = 0;
memset(vis, 0, sizeof(vis));
for(int i = 1; i <= x; i++) {
int sg = getSG(max(0, i-3)) ^ getSG(max(0, x-i-2));
vis[sg] = true;
}
for(int i = 0; i < MAXN; i++) if(!vis[i]) return SG[x] = i;
return -1;
}
bool Will_Win()
{
for(int i = 0; i < Len; i++)
if(s[i] == '.') {
s[i] = 'X';
if(Now_Win()) { s[i] = '.'; return false; }
s[i] = '.';
}
int sg = 0, space = 0;
for(int i = 0; i < Len; i++)
if(s[i] == 'X' || (i && s[i-1] == 'X') || (i > 1 && s[i-2] == 'X') || (i < Len-1 && s[i+1] == 'X') || (i < Len-2 && s[i+2] == 'X'))
{
sg ^= getSG(space);
space = 0;
}
else space++;
sg ^= getSG(space);
return sg == 0;
}
void solve()
{
CNT = 0;
Len = strlen(s);
for(int i = 0; i < Len; i++)
{
if(s[i] == 'X') continue;
s[i] = 'X';
if(Now_Win() || Will_Win()) Step[++CNT] = i + 1;
s[i] = '.';
}
}
int main()
{
memset(SG, -1, sizeof(SG));
int T; SF("%d", &T); while(T--) {
SF("%s", s);
solve();
if(CNT) {
PF("WINNING\n%d", Step[1]);
for(int i = 2; i <= CNT; i++) PF(" %d", Step[i]);
puts("");
}
else PF("LOSING\n\n");
}
}