HDU-1847 Good Luck in CET-4 Everybody!

本文解析了HDU-1847博弈问题,通过动态规划方法找到胜负规律:石子数为3的倍数时先手必败,其余情况下先手必胜。采用记忆化搜索优化递归过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

HDU-1847

题意

给你一堆石子,两人轮流取,每次只能取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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值