Loading

POJ2311 Cutting Game(二维SG)

链接:https://ac.nowcoder.com/acm/problem/51073
来源:牛客网

题目描述

Urej loves to play various types of dull games. He usually asks other people to play with him. He says that playing those games can show his extraordinary wit. Recently Urej takes a great interest in a new game, and Erif Nezorf becomes the victim. To get away from suffering playing such a dull game, Erif Nezorf requests your help. The game uses a rectangular paper that consists of W*H grids. Two players cut the paper into two pieces of rectangular sections in turn. In each turn the player can cut either horizontally or vertically, keeping every grids unbroken. After N turns the paper will be broken into N+1 pieces, and in the later turn the players can choose any piece to cut. If one player cuts out a piece of paper with a single grid, he wins the game. If these two people are both quite clear, you should write a problem to tell whether the one who cut first can win or not.

输入描述:

The input contains multiple test cases. Each test case contains only two integers W and H(2≤W,H≤200)(2 \leq W, H \leq 200)(2≤W,H≤200) in one line, which are the width and height of the original paper.

输出描述:

For each test case, only one line should be printed. If the one who cut first can win the game, print "WIN", otherwise, print "LOSE".

示例1

输入

[复制](javascript:void(0)😉

2 2
3 2
4 2

输出

[复制](javascript:void(0)😉

LOSE
LOSE
WIN

二维SG。首先可以知道\(1\times 1\)可以通过\(x\times 1\)得到,因此\(x\times 1\)两者都不会剪出来(x为长或者宽),因此得到\(1\times 1\)只能通过\(2\times 2,2\times 3,3\times2\)这三种局面得到。若先手面临这三种局面,不管怎么剪都会剪出来\(x\times 1\),因此这是必败态,其SG值为0。然后需要做的就是求出来所有可能状态的SG值然后直接查询,如果为0则lose,否则win。求SG值可以直接循环求,也可以选择递归+记忆化,对于一种状态,要生成其子局面可以选择剪长或者剪宽(遍历的时候绕过\(1\times x\)的情况),将生成的子游戏的值异或起来得到子局面的SG值,再对子局面的值求mex即可。

注意如果选择记忆化搜索,则一定要在函数里开vis数组求mex而非全局数组,因为递归的过程可能会破坏掉父状态的vis数组!

#include <bits/stdc++.h>
using namespace std;
int ww, hh;
int sg[255][255];

int getSG(int w, int h) {
	bool vis[305];//为什么vis放在里面就能过7 7这组样例?
	//因为函数里面有递归!递归时会改变全局数组!
	memset(vis, 0, sizeof(vis));
	if(sg[w][h] != -1) return sg[w][h];
	for(int k = 2; k <= w - k; k++) {
		vis[getSG(k, h) ^ getSG(w - k, h)] = 1;
	}
	for(int k = 2; k <= h - k; k++) {
		vis[getSG(w, k) ^ getSG(w, h - k)] = 1;
	}
	int t = 0;
	while (vis[t]) ++t;
	return sg[w][h] = t;
}
int main() {
	memset(sg, -1, sizeof(sg));
	sg[3][2] = sg[2][3] = sg[2][2] = 0;
	while(cin >> ww >> hh) {
		if(getSG(ww, hh)) cout << "WIN" << endl;
		else cout << "LOSE" << endl;
	}
	return 0;
}
posted @ 2021-05-05 10:08  脂环  阅读(75)  评论(0编辑  收藏  举报