题目描述
20~30%
直接暴力,前几个点可以过
另10%
因为N=1,所以直接判断M输出
100%
因为所有操作都是斜向的,所以可以把格子黑白染色,分成两个独立的游戏,于是可以博弈
每次考虑其中的一个矩阵的SG,选取其中的一个点看作其的一种情况。
显然每种情况都是一个局面,而这个局面的SG就是所有子游戏SG的异或和。
所以分LRX三种情况讨论,最后取mex
code
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define max(a,b) (a>b?a:b)
#define min(a,b) (a<b?a:b)
using namespace std;
struct A{
int s,x1,y1,x2,y2;
} d[160001];
char a[21][21];
char b[21][21];
char c[21][21];
bool bz[21][21][21][21];
bool Bz[21][21][21][21];
int sg[21][21][21][21];
int Sg[21][21][21][21];
bool sg2[401];
bool Sg2[401];
int n,m,i,j,k,l,N,I,X1,Y1,X2,Y2,s;
bool cmp(A a,A b)
{
return a.s<b.s;
}
int main()
{
while (scanf("%d%d",&n,&m)!=EOF)
{
memset(a,' ',sizeof(a));
memset(b,' ',sizeof(b));
memset(c,' ',sizeof(c));
memset(bz,0,sizeof(bz));
memset(Bz,0,sizeof(Bz));
memset(sg,0,sizeof(sg));
memset(Sg,0,sizeof(Sg));
N=max(n,m);
fo(i,1,n)
{
scanf("\n");
fo(j,1,m)
scanf("%c",&a[i][j]);
}
fo(i,1,N)
{
fo(j,1,N)
{
if ((i+j)&1)
b[(i-j+1)/2-(2-N)/2+1][(i+j+1)/2]=a[i][j];
else
c[(i-j)/2-(1-N)/2+1][(i+j)/2]=a[i][j];
}
}
I=0;
fo(i,1,N)
{
fo(j,1,N)
{
fo(k,i,N)
{
fo(l,j,N)
{
I++;
d[I].s=(k-i+1)*(l-j+1);
d[I].x1=i;
d[I].y1=j;
d[I].x2=k;
d[I].y2=l;
if (i==k && j==l)
{
if (b[i][j]=='R' || b[i][j]=='L' || b[i][j]=='X')
{
bz[i][j][k][l]=1;
sg[i][j][k][l]=1;
}
if (c[i][j]=='R' || c[i][j]=='L' || c[i][j]=='X')
{
Bz[i][j][k][l]=1;
Sg[i][j][k][l]=1;
}
}
}
}
}
}
sort(d+1,d+I+1,cmp);
j=1;
while (j<=I && d[j].s==1)
j++;
fo(i,j,I)
{
memset(sg2,0,sizeof(sg2));
memset(Sg2,0,sizeof(Sg2));
X1=d[i].x1;
Y1=d[i].y1;
X2=d[i].x2;
Y2=d[i].y2;
if (X1==X2)
{
bz[X1][Y1][X2][Y2]=bz[X1][Y1][X2][Y1]|bz[X1][Y1+1][X2][Y2];
Bz[X1][Y1][X2][Y2]=Bz[X1][Y1][X2][Y1]|Bz[X1][Y1+1][X2][Y2];
}
else
{
bz[X1][Y1][X2][Y2]=bz[X1][Y1][X1][Y2]|bz[X1+1][Y1][X2][Y2];
Bz[X1][Y1][X2][Y2]=Bz[X1][Y1][X1][Y2]|Bz[X1+1][Y1][X2][Y2];
}
fo(j,X1,X2)
{
fo(k,Y1,Y2)
{
s=0;
switch (b[j][k])
{
case 'L':
{
if (X1<j && bz[X1][Y1][j-1][Y2])
s^=sg[X1][Y1][j-1][Y2];
if (j<X2 && bz[j+1][Y1][X2][Y2])
s^=sg[j+1][Y1][X2][Y2];
break;
}
case 'R':
{
if (Y1<k && bz[X1][Y1][X2][k-1])
s^=sg[X1][Y1][X2][k-1];
if (k<Y2 && bz[X1][k+1][X2][Y2])
s^=sg[X1][k+1][X2][Y2];
break;
}
case 'X':
{
if (X1<j && Y1<k && bz[X1][Y1][j-1][k-1])
s^=sg[X1][Y1][j-1][k-1];
if (X1<j && k<Y2 && bz[X1][k+1][j-1][Y2])
s^=sg[X1][k+1][j-1][Y2];
if (j<X2 && Y1<k && bz[j+1][Y1][X2][k-1])
s^=sg[j+1][Y1][X2][k-1];
if (j<X2 && k<Y2 && bz[j+1][k+1][X2][Y2])
s^=sg[j+1][k+1][X2][Y2];
break;
}
}
if (b[j][k]=='L' || b[j][k]=='R' || b[j][k]=='X')
sg2[s]=1;
s=0;
switch (c[j][k])
{
case 'L':
{
if (X1<j && Bz[X1][Y1][j-1][Y2])
s^=Sg[X1][Y1][j-1][Y2];
if (j<X2 && Bz[j+1][Y1][X2][Y2])
s^=Sg[j+1][Y1][X2][Y2];
break;
}
case 'R':
{
if (Y1<k && Bz[X1][Y1][X2][k-1])
s^=Sg[X1][Y1][X2][k-1];
if (k<Y2 && Bz[X1][k+1][X2][Y2])
s^=Sg[X1][k+1][X2][Y2];
break;
}
case 'X':
{
if (X1<j && Y1<k && Bz[X1][Y1][j-1][k-1])
s^=Sg[X1][Y1][j-1][k-1];
if (X1<j && k<Y2 && Bz[X1][k+1][j-1][Y2])
s^=Sg[X1][k+1][j-1][Y2];
if (j<X2 && Y1<k && Bz[j+1][Y1][X2][k-1])
s^=Sg[j+1][Y1][X2][k-1];
if (j<X2 && k<Y2 && Bz[j+1][k+1][X2][Y2])
s^=Sg[j+1][k+1][X2][Y2];
break;
}
}
if (c[j][k]=='L' || c[j][k]=='R' || c[j][k]=='X')
Sg2[s]=1;
}
}
j=0;
while (sg2[j]) j++;
sg[X1][Y1][X2][Y2]=j;
j=0;
while (Sg2[j]) j++;
Sg[X1][Y1][X2][Y2]=j;
}
if (sg[1][1][N][N]^Sg[1][1][N][N])
printf("WIN\n");
else
printf("LOSE\n");
}
}