【蓝桥杯】 取球游戏 (博弈问题)

50 篇文章 1 订阅
49 篇文章 0 订阅
今盒子里有n个小球,A、B两人轮流从盒中取球,每个人都可以看到另一个人取了多少个,也可以看到盒中还剩下多少个,并且两人都很聪明,不会做出错误的判断。
我们约定:
每个人从盒子中取出的球的数目必须是:1,3,7或者8个。
轮到某一方取球时不能弃权!
A先取球,然后双方交替取球,直到取完。
被迫拿到最后一个球的一方为负方(输方)

请编程确定出在双方都不判断失误的情况下,对于特定的初始球数,A是否能赢?

分析:

 f(局面 x) ---> 胜负   

边界条件处理 

for(对我所有可能的走法)

{      试着走一步 -----> 局面y 

      胜负 t = f(y);    

   if(t==负) return 胜    局面  

  return 负 

也就是说,让A去尝试它走哪一步不会输,他走出一步后,局面发生改变,由对手去下剩下的局面,通过判断对手的输赢来判断自己的输赢。

解法一:

public class Main {
	public static boolean f(int n)   
	{
		if(n==0) return true;  //边界处理,不论对于哪方来说,如果拿的时候没有球可拿,则说明最后一个球被对方拿走,自己就赢了
		if(n>=1&&f(n-1)==false) return true;  //对A来说,如果球数大于一个,就先尝试着去一个,如果取一个,对方输了,就返回true,代表我方赢
		if(n>=3&&f(n-3)==false) return true;   //否则尝试着取3个球,以此类推,如果所有尝试都不可以取胜,则返回false。
		if(n>=7&&f(n-7)==false) return true;
		if(n>=8&&f(n-8)==false) return true;
		return false;
	}
public static void main(String[] args) {
	System.out.println(f(10));
	System.out.println(f(1));
	System.out.println(f(4));
}
}

解法二:根据题目的意思,我们可以推出一些局面的情况。

由于题目的要求,两个人取球,其中每人每一次必取 1, 3, 7, 8 其中的一个数量的球,并且最后一个球被取到的人输,因此我得出以下表格:

先我拿先他拿记录表表示了初始的总球数,所对应的游戏情况
我败我胜13571618202231.....
我胜我败2468910111213.....

表格中的 失败 胜利,均是相对于“我”而言的。

因此对于A君先取球,判断A君的游戏情况,可以把“我先拿胜利”的情况均存在r[]数组中并赋值为1,否则r[]数组中其他值赋值为0,即可。

表格的具体构造过程如下:

初始值:int r[10003]={1,0,1,0,1,0,1,0,1}; //*-1表示0个球的情况不存在,存了8个球进去了下标从0开始的 *//

然后 i = 9;判断 ( r[i-8]==1&& r[i-3]==1&& r[i-7]==1 && r[i-1]==1 ),

如果成立,说明无论我走哪一步,对方都可以胜利, 则r[i] = 1  否则r[i] = 0;

代码:

public class Main {
public static void main(String[] args) {
	int[] book = new int[1000];
	book[0] = -1; book[1] = 0; book[2] = 1;
	book[3] = 0;  book[4] =1; book[5] = 0;
	book[6] = 1; book[7]=0;   book[8] = 1;
	for(int i=9;i<book.length;i++)
	{
		if((book[i-1]==0)&&(book[i-3]==0)&&(book[i-7]==0)&&(book[i-8])==0)
		{
			book[i] = 0;
		}else {
			book[i] =1;
		}
	}
  System.out.println(book[10]);
}
}

总结:代码一采用递归的形式写,效率不是很高,方式二时间复杂度为N,值的推荐。

这是没有平局的博弈问题,有平局的可参考后面的博文。


  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值