题意
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;
}