白书-poj2311 Cutting Game(SG函数)

题目

给定w*h的格纸,轮流沿格线切割,

当前有好几块格纸的,可以挑任意一块切,

先切出一个1*1方格的一方获胜,

给定w和h(2<=w,h<=200),问谁必胜

思路来源

《挑战程序竞赛》第二版

题解

注意到如果切割出了1*h或者w*1的纸张

则下一步对手一定会切这一张,使己方必败

所以切的时候,只考虑在大于等于2的行和列里转移

剩下答案就是两个子局面的异或了,SG函数常规操作

心得

补白书.jpg

马上就要期末复习了,有点恋恋不舍,什么都想刷一点

SG函数这个set的写法挺好的,也不用开个大数组每次清空vis

而且注意到sg函数的值只和初始局面有关,与从什么状态转移来无关,

故只需memset一次dp数组,之后就利用现成结果就可以了

代码

#include
#include
#include
#include
using namespace std;
int r,c;
int dp[205][205];
int sg(int w,int h) 
{
	if(~dp[w][h])return dp[w][h];
	setq;
	for(int i=2;w-i>=2;++i)
	q.insert(sg(i,h)^sg(w-i,h));
	for(int j=2;h-j>=2;++j)
	q.insert(sg(w,j)^sg(w,h-j));
    int res=0;
	while(q.count(res))res++;
	return dp[w][h]=res;
}
int main()
{
	memset(dp,-1,sizeof dp);
	while(~scanf("%d%d",&r,&c))
	puts(sg(r,c)?"WIN":"LOSE");
	return 0;
}

 

你可能感兴趣的:(博弈)