题意
给你一堆石子,两人轮流取,每次只能取2的幂次数目(1,2,4,8…)个石子,取到最后一个石子的获胜。
思路
SG函数打表找规律:石子数是3的倍数时先手必败,否则先手必胜。
这里用动态规划的思想,设计出递归型动规程序,说白了就是记忆化搜索。用一个bool数组记录每个n的胜败情况。
必胜态一定有一条路一步进入必败态,必败态一步无论如何只能进入必胜态。具体解释看代码注释吧。
#include<iostream>
#include<cstring>
using namespace std;
bool dp[1001];//记录所有的胜败局面
bool f(int n)//如果还剩n个石子是必胜态就返回true,否则返回false
{
if(n==0)//还剩0个石子就是必败态
return false;
if(dp[n])//如果之前算过dp[n]为1的话就直接返回
return true;
for(int i=1;i<=n;i*=2)
{//循环遍历每种取石子的方法
if(f(n-i)==false)//如果取完i个石子的状态是必败态
{
dp[n]=1;//现在就是必胜态,记录下来
return true;//返回
}
}
return false;//如果所有走法都试过还没有返回就说明现在是必败态
}
int main()
{
int n;
while(cin>>n)
{
memset(dp,0,sizeof(dp));
if(f(n))
cout<<"Kiki"<<endl;
else
cout<<"Cici"<<endl;
}
return 0;
}