[POJ2311]Cutting Game

vjudge

题意

有一张\(W*H\)大小的网格纸,每个人每次可以选择一块纸片沿任意一条网格线剪开,先剪出\(1*1\)大小方格者胜。
问是否先手必胜。\(2\le W,H\le200\)

sol

首先,像这样“谁先balabala”的问题是不能直接用\(SG\)函数去做的。
考虑一下问题的转化:两者都不能把网格纸剪到有一维为\(1\)(不然对手就直接再剪一刀获胜了),不能操作者败。
这样就可以直接用\(SG\)求了。
预处理每个状态的\(SG\)值,枚举这一刀在哪里剪,可以把原问题分割成两个独立的子问题,而这个状态下的\(SG\)值就是两个子问题的\(SG\)值的\(Nim\)和(就是异或和啦)。
状态数量\(O(n^2)\),转移复杂度\(O(n)\),总复杂度\(O(n^3)\)

code

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int N = 205;
int SG[N][N],b[N],W,H;
int main()
{
	for (int n=2;n<=200;++n)
		for (int m=2;m<=200;++m)
		{
			memset(b,0,sizeof(b));
			for (int i=2;n-i>=2;++i) b[SG[i][m]^SG[n-i][m]]=1;
			for (int i=2;m-i>=2;++i) b[SG[n][i]^SG[n][m-i]]=1;
			for (int i=0;i<=200;++i) if (!b[i]) {SG[n][m]=i;break;}
		}
	while (scanf("%d%d",&W,&H)!=EOF) puts(SG[W][H]?"WIN":"LOSE");
	return 0;
}
posted @ 2018-03-28 19:31  租酥雨  阅读(733)  评论(0编辑  收藏  举报