$ color{#0066ff}{ 题目描述 }$
n*m的格子,每个格子有字符'L','R',X',初始可以选择所有格子.
当选了 'L'的格子时,当前格子左下右上这条线上所有点不能选;
当选了 'R'的格子时,当前格子右下左上这条线上所有点不能选;
当选了 'X'的格子时,就是相当于同时选了'L','R';
如果不是最后选的输出'WIN',否则输出'LOSE'
(color{#0066ff}{输入格式})
第一行两个正整数 (n,m) 表示网格大小
接下来是格子
(color{#0066ff}{输出格式})
如果不是最后选的输出'WIN',否则输出'LOSE'
(color{#0066ff}{输入样例})
2 2
RL
LR
2 2
RR
RR
(color{#0066ff}{输出样例})
LOSE
WIN
(color{#0066ff}{数据范围与提示})
1<=n,m<=20
(color{#0066ff}{题解})
对于对角线的切割,我们不好处理,考虑旋转坐标系
然后,方格就形成了一个菱形,每次我们或横切或纵切,或者一起
然后发现,对这个菱形黑白染色,黑和白是不会互相影响的!于是我们就分成了2个游戏
我用坐标范围来表示当前的状态,每次枚举所有格子,转移到两个或四个游戏,异或起来作为后继状态
直接SG定理即可
#include<bits/stdc++.h>
#define LL long long
LL in() {
char ch; LL x = 0, f = 1;
while(!isdigit(ch = getchar()))(ch == '-') && (f = -f);
for(x = ch ^ 48; isdigit(ch = getchar()); x = (x << 1) + (x << 3) + (ch ^ 48));
return x * f;
}
const int maxn = 55;
int n, m;
int sg[maxn][maxn][maxn][maxn][2];
char mp[maxn][maxn];
bool vis[1002020];
int work(int xmin, int xmax, int ymin, int ymax, int tp) {
if(xmin > xmax || ymin > ymax) return 0;
int &now = sg[xmin][xmax][ymin][ymax][tp];
if(~now) return now;
now = 0;
for(int x = 1; x <= n; x++)
for(int y = 1; y <= m; y++)
if(((x + y) & 1) == tp) {
int xx = x + y, yy = x - y + m;
if(xmin <= xx && xx < xmax && ymin <= yy && yy < ymax) {
if(mp[x][y] == 'L') work(xmin, xx, ymin, ymax, tp), work(xx + 1, xmax, ymin, ymax, tp);
if(mp[x][y] == 'R') work(xmin, xmax, ymin, yy, tp), work(xmin, xmax, yy + 1, ymax, tp);
if(mp[x][y] == 'X') work(xmin, xx, ymin, yy, tp), work(xmin, xx, yy + 1, ymax, tp),
work(xx + 1, xmax, ymin, yy, tp), work(xx + 1, xmax, yy + 1, ymax, tp);
}
}
for(int x = 1; x <= n; x++)
for(int y = 1; y <= m; y++)
if(((x + y) & 1) == tp) {
int xx = x + y, yy = x - y + m;
if(xmin <= xx && xx < xmax && ymin <= yy && yy < ymax) {
if(mp[x][y] == 'L') vis[sg[xmin][xx][ymin][ymax][tp] ^ sg[xx + 1][xmax][ymin][ymax][tp]] = true;
if(mp[x][y] == 'R') vis[sg[xmin][xmax][ymin][yy][tp] ^ sg[xmin][xmax][yy + 1][ymax][tp]] = true;
if(mp[x][y] == 'X') vis[sg[xmin][xx][ymin][yy][tp] ^ sg[xmin][xx][yy + 1][ymax][tp] ^
sg[xx + 1][xmax][ymin][yy][tp] ^ sg[xx + 1][xmax][yy + 1][ymax][tp]] = true;
}
}
while(vis[now]) now++;
for(int x = 1; x <= n; x++)
for(int y = 1; y <= m; y++)
if(((x + y) & 1) == tp) {
int xx = x + y, yy = x - y + m;
if(xmin <= xx && xx < xmax && ymin <= yy && yy < ymax) {
if(mp[x][y] == 'L') vis[sg[xmin][xx][ymin][ymax][tp] ^ sg[xx + 1][xmax][ymin][ymax][tp]] = false;
if(mp[x][y] == 'R') vis[sg[xmin][xmax][ymin][yy][tp] ^ sg[xmin][xmax][yy + 1][ymax][tp]] = false;
if(mp[x][y] == 'X') vis[sg[xmin][xx][ymin][yy][tp] ^ sg[xmin][xx][yy + 1][ymax][tp] ^
sg[xx + 1][xmax][ymin][yy][tp] ^ sg[xx + 1][xmax][yy + 1][ymax][tp]] = false;
}
}
return now;
}
char getch() {
char ch;
while(!isalpha(ch = getchar()));
return ch;
}
int main() {
n = in(), m = in();
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++)
mp[i][j] = getch();
memset(sg, -1, sizeof sg);
puts(work(2, n + m + 3, 1, n + m + 3, 0) ^ work(1, n + m + 3, 1, n + m + 3, 1)? "WIN" : "LOSE");
return 0;
}