CF138D World of Darkraft

$ \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;
}
posted @ 2019-03-08 17:06  olinr  阅读(480)  评论(0编辑  收藏  举报