题目
给定w*h的格纸,轮流沿格线切割,
当前有好几块格纸的,可以挑任意一块切,
先切出一个1*1方格的一方获胜,
给定w和h(2<=w,h<=200),问谁必胜
思路来源
《挑战程序竞赛》第二版
题解
注意到如果切割出了1*h或者w*1的纸张
则下一步对手一定会切这一张,使己方必败
所以切的时候,只考虑在大于等于2的行和列里转移
剩下答案就是两个子局面的异或了,SG函数常规操作
心得
补白书.jpg
马上就要期末复习了,有点恋恋不舍,什么都想刷一点
SG函数这个set的写法挺好的,也不用开个大数组每次清空vis
而且注意到sg函数的值只和初始局面有关,与从什么状态转移来无关,
故只需memset一次dp数组,之后就利用现成结果就可以了
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<set>
using namespace std;
int r,c;
int dp[205][205];
int sg(int w,int h)
{
if(~dp[w][h])return dp[w][h];
set<int>q;
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;
}