【分割问题】-取石子游戏

信息学奥赛一本通(C++版)在线评测系统


解题思路:

(1)题目还是比较容易懂的,但是操作起来有一些难度,有两堆石子块儿,每次只能从大的里面取小的数量的整数倍,然后一直到有一方全部拿空便为取胜。

(2)里面有一句特别关键的话,叫做两个人都采取最优策略,这是什么意思呢?意思当式子数量确定的时候,两个人都已经经过精确的计算,每一步应该怎么拿,然后确保自己能够胜利,如果还是很抽象,那么看一下示例:

   

 对于25和7是有4种方案的,并且不同的方案赢的选手也不一样,但是题目说,选手都会按照最优策略来取,所以选手1保证赢的话,会按照第二种方案,这样先手赢

(3)这道博弈论的题为什么会出现在搜索里呢?因为每次取都会按照较小值的整数倍来取,需要枚举每一种方案。设dfs(a,b)函数为取的两堆石子块,(a>=b),递归出口为当a%b==0的时候,那么就可以一次取完a,获胜。

(4)如何判断是先手赢还是后手赢呢?可以设置一个计数器,可以发现,如果a%b==0的时候,如果当前是偶数的时候,表示是选手2取,那么后手赢,反之先手赢

(5)题目中还有一条特别关键的信息,叫做a/b>=2的时候,先手必赢,那么递归出口便增加了一个条件,这样会大大缩小时间复杂度(想想为什么呢?)


#include<bits/stdc++.h>
using namespace std;

int a,b;
bool flag;//用来标记先手是否赢 

void dfs(int x,int y,int cnt)
{
	if(x<y)
	swap(x,y);
	
	if(x%y==0||x/y>=2)//如果x能被y整除,即把x全部取掉胜利 
	{
		if(cnt%2==1)//如果是奇数,说明是先手最后取的
		flag=1;//打上标记 	
		
		return ;//递归出口 
	}
	else
	{
		for(int i=1;i<=x/y;i++)//枚举可以取的整数倍 
		{
			dfs(x-i*y,y,cnt+1);//继续下一次递归
		} 
	}
}
int main()
{
	while(1)
	{
		cin>>a>>b;
		if(a==0&&b==0)//结束条件
		break;

		dfs(a,b,1);//开始深搜
		if(flag==1)
		cout<<"win"<<endl;
		else
		cout<<"lose"<<endl;
		
		flag=0;//标记初始化 
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值