Codeforces 138D Nim + SG

题意

传送门 Codeforces 138D

题解

发生分割的游戏,考虑 G r u n d y Grundy Grundy 值。与直接分割平面不同之处在于游戏场地是方格状的,考虑将平面上的格子沿主对角线交替染为黑(坐标和为奇数)、白色(坐标和为偶数),黑色与白色格子切割时是互不影响的。那么将游戏按黑白格子考虑两个独立的分割游戏,用 N i m Nim Nim 游戏的方法判断胜负。

为了方便处理,将矩形旋转 45 45 45 度,即同一条主对角线的点横坐标相同,同一条副对角线上的点纵坐标相同,然后将最小值设为零,即 ( x , y ) (x,y) (x,y) 映射为 ( x + y , y − x + M − 1 ) (x+y,y-x+M-1) (x+y,yx+M1)。此时考虑横纵向的分割即可。

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
using namespace std;
#define maxn 45
int N, M, mem[maxn][maxn][maxn][maxn][2];
char mp[maxn][maxn];

int gs(int x1, int x2, int y1, int y2, int f)
{
    int &res = mem[x1][x2][y1][y2][f];
    if (res != -1)
        return res;
    bool s[maxn] = {0};
    for (int y = 0; y < N; ++y)
    {
        for (int x = 0; x < M; ++x)
        {
            int _x = x + y, _y = y - x + M - 1;
            if ((_x & 1) == f)
            {
                if (x1 <= _x && _x < x2 && y1 <= _y && _y < y2)
                {
                    int g;
                    char c = mp[y][x];
                    if (c == 'L')
                        g = gs(x1, _x, y1, y2, f) ^ gs(_x + 1, x2, y1, y2, f);
                    else if (c == 'R')
                        g = gs(x1, x2, y1, _y, f) ^ gs(x1, x2, _y + 1, y2, f);
                    else
                        g = gs(x1, _x, y1, _y, f) ^ gs(_x + 1, x2, y1, _y, f) ^ gs(x1, _x, _y + 1, y2, f) ^ gs(_x + 1, x2, _y + 1, y2, f);
                    s[g] = 1;
                }
            }
        }
    }
    while (s[++res])
        ;
    return res;
}

int main()
{
    scanf("%d%d", &N, &M);
    for (int i = 0; i < N; ++i)
        scanf(" %s", mp + i);
    memset(mem, -1, sizeof(mem));
    puts(gs(0, N + M - 1, 0, N + M - 1, 0) ^ gs(0, N + M - 1, 0, N + M - 1, 1) ? "WIN" : "LOSE");
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值