$POJ2311\ Cutting\ Game$ 博弈论

正解:博弈论

解题报告:

传送门!

首先看到说,谁先$balabala$,因为$SG$函数是无法解决这类问题的,于是考虑转化成"不能操作者赢/输"的问题,不难想到先剪出$1\cdot 1$一定是对手剪出了一个$1\cdot n$的格子,于是就变成,不能剪出$1\ x\ n$的格子,不能操作者败

然后就可以直接用$SG$函数,,,?就对于$n\cdot m$的一个局面,剪一道就相当于分成了$i\cdot m$,$(n-i)\cdot m$的两个子游戏(竖着剪差不多就先只讨论横着剪了昂$QwQ$

然后就可以先预处理,爆枚所有局面求这个局面的$SG$函数值,具体来说就开个桶,枚举从哪儿剪的,把所有出边的$SG$值存下来,然后根据$mex$的定义直接从小到大枚举找到$mex$就好

啊好像说得不太清楚$QAQ$,,,?算了看代码就成$QwQ$

#include<bits/stdc++.h>
using namespace std;
#define il inline
#define gc getchar()
#define ri register int
#define rb register bool
#define rc register char
#define rp(i,x,y) for(ri i=x;i<=y;++i)

const int N=200+10;
int x,y,vis[N][N],sg[N][N];

il int read()
{
    rc ch=gc;ri x=0;rb y=1;
    while(ch!='-' && (ch>'9' || ch<'0'))ch=gc;
    if(ch=='-')ch=gc,y=0;
    while(ch>='0' && ch<='9')x=(x<<1)+(x<<3)+(ch^'0'),ch=gc;
    return y?x:-x;
}

int main()
{
    rp(i,2,200)
        rp(j,2,200)
        {
            memset(vis,0,sizeof(vis));
            rp(k,2,j-2)vis[sg[i][k]^sg[i][j-k]]=1;
            rp(k,2,i-2)vis[sg[k][j]^sg[i-k][j]]=1;
            rp(k,1,200)if(!vis[k])sg[i][j]=k,k=201;
        }
    while(scanf("%d%d",&x,&y)!=EOF)printf(sg[x][y]?"WIN":"LOSE");
    return 0;
}
View Code

猜你喜欢

转载自www.cnblogs.com/lqsukida/p/10852928.html