codeforces 138D_World of Darkraft_SG函数

题意

H*W的棋盘中每个点都是L、R、X三者之一,两人轮流选一个点,若为L则向左下和右上发射激光,R向右下和左上发射,X则相当于LR的组合——同时向四个方向发射。激光所至的点会被摧毁,只有已摧毁的点或棋盘边界才会挡住激光。若在某回合开始时所有点都被摧毁,则该人失败。问先手是否有必胜策略?

思路

1。将棋盘分成单双两部分,即两个子问题
为什么一定要分成两个子问题,过了好几天终于想通了。如果不分成两个子问题,白子画一条斜线,黑线也无法跨越。而原问题中,这种情况黑线是要跨越过去的。
2。假想将棋盘旋转45度,即将问题转化成将一个矩形分割成几个矩形,即几个矩形
3。在此基础上用SG函数
原题解链接:http://www.hankcs.com/program/algorithm/codeforces-138d-world-of-darkraft-notes-challenge-programming-contest.html

链接

http://codeforces.com/contest/138/problem/D

代码

#include<iostream>
#include<cstring>
#include<cstdio>

using namespace std;

const int maxn = 45;

int n, m;
char G[maxn][maxn];

int sg[maxn][maxn][maxn][maxn][2];

int SG(int x0, int x1, int y0, int y1, int d){
    int &g = sg[x0][x1][y0][y1][d];
    if(g != -1) return g;

    char s[maxn * 2 + 1] = {0};
    for (int y = 0; y < n; ++y){
        for (int x = 0; x < m; ++x){
            if (((x + y) & 1) == d){
                int x_ = y + x, y_ = y - x + m;
                if (x0 <= x_ && x_ < x1 && y0 <= y_ && y_ < y1){
                    int tmp;
                    if (G[y][x] == 'L'){
                        tmp = SG(x0, x_, y0, y1, d) ^ SG(x_ + 1, x1, y0, y1, d);
                    }
                    if (G[y][x] == 'R'){
                        tmp = SG(x0, x1, y0, y_, d) ^ SG(x0, x1, y_ + 1, y1, d);
                    }
                    if (G[y][x] == 'X'){
                        tmp = SG(x0, x_, y0, y_, d) ^ SG(x0, x_, y_ + 1, y1, d) ^
                                SG(x_ + 1, x1, y0, y_, d) ^ SG(x_ + 1, x1, y_ + 1, y1, d);
                    }
                    s[tmp] = 1;
                }
            }
        }
    }

    while (s[++g]);
    return g;
}

int main(){
    while(scanf("%d %d", &n, &m) == 2){
        for(int i = 0; i < n; ++i){
            scanf(" %s", G[i]);
        }

        memset(sg, -1, sizeof sg);

        if((SG(0, n + m, 0, n + m, 0) ^ SG(0, n + m, 0, n + m, 1)) > 0) puts("WIN");
        else puts("LOSE");
    }

    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值