您的位置:首页 > 其它

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

2018-03-26 16:09 218 查看
今盒子里有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,值的推荐。
这是没有平局的博弈问题,有平局的可参考后面的博文。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: