Codeforces 168D Wizards and Huge Prize
传送门:http://codeforces.com/problemset/problem/168/d
思路:这题比较恶心,细节很多,不过还好cf可以看数据...
首先考虑一个弱化版,只会横着或竖着以及横着和竖着一起来。
我们可以发现,一次操作后就相当于把一个大的游戏分成1或2或4个独立小游戏
SG值与位置也有关系,所以SG[u][d][l][r]表示左上坐标为(u,d)右下坐标为(l,r)的SG值
然后对于斜着的,我们考虑把它旋转45度,但是这有一个问题,一次操作并不能分出几个独立的小游戏(画图就可以发现了)
于是考虑把棋盘黑白染色,这样就可以分出独立的游戏了。
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; int sg[25][25][25][25],b[25][25],n,N,M;char a[25][25];bool bo[1010]; int work(int u,int d,int l,int r){ if (u>d||l>r) return 0; if (sg[u][d][l][r]!=-1) return sg[u][d][l][r]; for (int i=u;i<=d;i++) for (int j=l;j<=r;j++) if (b[i][j]==1) work(u,i-1,l,r),work(i+1,d,l,r); else if (b[i][j]==2) work(u,d,l,j-1),work(u,d,j+1,r); else if (b[i][j]==3) work(u,i-1,l,j-1),work(u,i-1,j+1,r),work(i+1,d,l,j-1),work(i+1,d,j+1,r); memset(bo,0,sizeof(bo)); for (int i=u;i<=d;i++) for (int j=l;j<=r;j++) if (b[i][j]==1) bo[work(u,i-1,l,r)^work(i+1,d,l,r)]=1; else if (b[i][j]==2) bo[work(u,d,l,j-1)^work(u,d,j+1,r)]=1; else if (b[i][j]==3) bo[work(u,i-1,l,j-1)^work(u,i-1,j+1,r)^work(i+1,d,l,j-1)^work(i+1,d,j+1,r)]=1; for (int i=0;;i++) if (!bo[i]) return sg[u][d][l][r]=i; } int getans(int odd){ memset(sg,-1,sizeof(sg)); memset(b,0,sizeof(b)); for (int i=1;i<=N;i++) for (int j=1;j<=M;j++) if (((i+j)&1)==odd) b[(i+j)>>1][(j-i+N+1)>>1]=a[i][j]=='L'?1:a[i][j]=='R'?2:3; /*for (int i=1;i<=n;i++,puts("")) for (int j=1;j<=n;j++) printf("%c",b[i][j]==1?'L':b[i][j]==2?'R':b[i][j]==3?'X':'0'); puts("");*/ return work(1,n,1,n); } int main(){ while (scanf("%d%d",&N,&M)!=EOF){ n=(N+M)>>1; for (int i=1;i<=N;i++) scanf("%s",a[i]+1); puts(getans(0)^getans(1)?"WIN":"LOSE"); } return 0; }