剪纸游戏

这一道题就是显然的multi-SG题目了(只是没有明显的后继节点,只能分解节点罢了)

其实蓝书上关于为什么不简单的给\(1\times 1\)赋值为\(0\)的说法不尽然。实际上根据multi-SG的证明过程,我们要求是无法行动的局面判负。如果我们以\(1\times\)X为终止局面,那么这里是还可以行动的额,而且接下来出现一个\(1\times 1\)的矩形,但是可能还有其他的矩形仍然可以被减,也就是还可以行动,但是已经可以判胜负了,这就不符合multi-SG的定义;所以我们不妨认为蓝书上说的三种情况是无法行动的状态(也就是有向图中既没有后继也不能分解的节点),这样就符合定义了(此时还不能判胜负),我们就将这三种情况作为边界即可

这里无论双方怎么决策,决策图都不可能出现1x某某的网格(原因见蓝书),所以我们在程序中就不要考虑SG[1][某某]

最后的不能分解的节点就是2x2,2x3,3x2(注意不要涉及1x某某哦),我们把这三个节点赋成0即可

然后对每一个节点枚举从哪里剪开(注意别枚举1x某某的决策,因为不会出现),然后按照multi-SG进行决策就行了

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=210;
int sg[N][N];
bool flag[N<<1];
int main()
{
	for(int i=2;i<=200;i++)
	for(int j=i;j<=200;j++)
	if((i==2&&(j==2||j==3))||(i==j&&j==3)) continue;
	else 
	{
		memset(flag,0,sizeof(flag));
		for(int k=2;k<j-1;k++) 
		flag[sg[min(k,i)][max(k,i)]^sg[min(j-k,i)][max(j-k,i)]]=1;
		for(int k=2;k<i-1;k++) 
		flag[sg[min(k,j)][max(k,j)]^sg[min(i-k,j)][max(i-k,j)]]=1;
		for(int k=0;k<=410;k++)
		if(!flag[k])
		{
			sg[i][j]=k;
			break;
		}
	}
	int n,m;
	while(scanf("%d%d",&n,&m)==2)
	if(sg[min(n,m)][max(n,m)]==0) printf("LOSE\n");
	else printf("WIN\n");
	return 0;
 } 
posted @ 2023-09-14 23:10  最爱丁珰  阅读(5)  评论(0编辑  收藏  举报