Cutting Game

Cutting Game

刚开始有一\(n\times m\)的矩形网格纸,双方轮流操作,剪网格纸,对于任意一个局面而言,你可以选择其中一张网格纸,把它剪成两个长宽都是整数的网格纸,剪出\(1\times 1\)的人获胜,询问先手是否能够获胜,\(n,m\leq 200\)

显然为博弈的题目,发现一张网格纸为一个有向图游戏,而剪出的网格纸为多个有向图游戏,考虑有向图游戏的和,注意到局面可以支持枚举,考虑SG函数,现在问题在于终止状态为只要一个有向图游戏结束就全部结束,这显然不是有向图游戏和能做到得,于是考虑更改边界,显然\(1\times x\ or\ x\times1\)是没人会剪出的,因为剪出意味着必败,转移时不予考虑,而出现\(2\times 2,2\times 3,3\times 2\)也不会有人继续剪,剪了就必败,于是易知这些都为必败局面,于是现在所定义的失败为所有的有向图游戏全部为必败局面即必败,因此我们就可以照着有向图游戏的和的套路解决问题了。

参考代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#define il inline
#define ri register
using namespace std;
int opt[201][201];
il int SG(int,int);
int main(){
    int n,m;memset(opt,-1,sizeof(opt));
    opt[3][2]=opt[2][3]=opt[2][2]=0;
    while(scanf("%d%d",&n,&m)!=EOF)
        puts(SG(n,m)?"WIN":"LOSE");
    return 0;
}
il int SG(int n,int m){
    if(opt[n][m]!=-1)return opt[n][m];
    int i;bool mex[201];memset(mex,0,sizeof(mex));
    for(i=2;i<<1<=n;++i)mex[SG(n-i,m)^SG(i,m)]|=true;
    for(i=2;i<<1<=m;++i)mex[SG(n,m-i)^SG(n,i)]|=true;
    i=0;while(mex[i])++i;return opt[n][m]=i;
}
posted @ 2019-05-13 13:56  a1b3c7d9  阅读(110)  评论(0编辑  收藏  举报