题目描述
传送门
一个一行n列的棋盘,两人轮流在上面下棋子,连成3个棋子的人获胜。问是否有必胜策略。
题解
可以发现如果在点i已经有了棋子,那么就不能在i-2,i-1,i+1,i+2这几个地方下棋子,否则就会让对方赢。
那么问题可以转化为在如果在点i已经有了棋子,那么就不能在i-2,i-1,i+1,i+2这几个地方下棋子,不能下棋子的人负。
如果长度为x的棋盘上点i处下了棋子的话,实际上就是将这个游戏分成了(i-3)和(x-i-2)两个游戏。
那么这就是一个典型的Multi-SG游戏了,可以用SG函数来解决。
记忆化搜索,时间复杂度
O(n2)
代码
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
#define N 2005
int n,sg[N],ans;
int get_sg(int x)
{
if (x<0) return 0;
if (sg[x]!=-1) return sg[x];
bool ext[N];memset(ext,0,sizeof(ext));
for (int i=1;i<=x;++i)
ext[get_sg(i-3)^get_sg(x-i-2)]=1;
for (int i=0;i<=x;++i)
if (!ext[i]){sg[x]=i;break;}
return sg[x];
}
int main()
{
memset(sg,-1,sizeof(sg));
while (~scanf("%d",&n))
{
ans=get_sg(n);
if (ans) puts("1");
else puts("2");
}
}