• 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;
    }
    
  • 相关阅读:
    容器常用命令
    镜像常用命令
    Docker安装
    Jenkins部署
    IIS配置伪静态 集成模式 样式丢失
    centos7 apache 配置ssl
    centOS7 关闭swap
    Presto集群部署和配置
    HDFS中将普通用户增加到超级用户组supergroup
    superset在 centos 7安装运行
  • 原文地址:https://www.cnblogs.com/olinr/p/10496954.html
Copyright © 2020-2023  润新知