在第I个位置放一个X,即可分为两个子游戏,I-3和n-I-2。
对于连成3个X的状态我们是不好表示的,因此我们不妨退一步,看看在连成3个X之前都是什么样的状态,只要避免这样的状态出现就行了。
画一下就会发现,实际上只有X_X和_XX_这样两种类型,其实想到这里就逐渐有眉目了,两个选手一定会避免走出上面的局面。因此当一个选手画了一个X之后,假设局面是12X34,其中数字代表空位,为了避免上面的情况出现,1、2、3、4这4个位置一定不能走,如果走了的话就必输了,因此我们就可以等效成画一个X之后X连同左右两边各两个格子都被拿掉了,这样就变成take and break类型的游戏了,具体的这类游戏的一些模型可以参考《Game Theory》这篇论文。于是,我们只要把连续的一段格子看成一个状态就可以了,每次画X的时候要么就是在某一端去掉一些格子,要么就是在中间去掉5个格子并把剩下的格子分成左右两部分,再要么如果n小的话就全被去掉了。然后用记忆化搜索求得各个状态的sg函数值即可。
#include<stdio.h>
#include <string.h>
#include <stdlib.h>
#include<math.h>
#define MAXN 2000+100
int A[MAXN];
int W,H;
int sg[MAXN];
int N;
int dfs(int n)
{
if(n<0) return 0;
if(sg[n]>=0)
return sg[n];
int g[MAXN]={0};
int i;
for( i=1;i<=n;i++)
{
g[dfs(i-3)^dfs(n-i-2)]=1;
}
for(i=0;;i++)
if(g[i]==0)
return sg[n]=i;
}
int main()
{
int i,j,ans;
memset(sg, -1, sizeof(sg));
while(scanf("%d",&N)!=EOF)
{
ans=dfs(N);
if(ans)
printf("1\n");
else
printf("2\n");
}
return 0;
}