这是我参与更文挑战的第14天,活动详情查看: [更文挑战]
你好呀,我是灰小猿,一个超会写bug的程序猿!
欢迎大家关注我的专栏“每日蓝桥”,该专栏的主要作用是和大家分享近几年蓝桥杯省赛及决赛等真题,解析其中存在的算法思想、数据结构等内容,帮助大家学习到更多的知识和技术!
标题:取球博弈
两个人玩取球的游戏.
一共有N个球,每人轮流取球,每次可取集合{n1,n2,n3}中的任何一个数目.
如果无法继续取球,则游戏结束.
此时,持有奇数个球的一方获胜.
如果两人都是奇数,则为平局.
假设双方都采用最聪明的取法,
第一个取球的人一定能赢吗?
试编程解决这个问题.
输人格式:
第一行3个正整数n1 n2n3,空格分开,表示每次可取的数目(0<nl,n2,n3<100)
第二行5个正整数x1 x2...x5,空格分开,表示5局的初始球数(0<xi<1000)
输出格式:
一行5个字符,空格分开.分别表示每局先取球的人能否获胜.
能获胜则输出+,
次之,如有办法逼平对手,输出0,
无论如何都会输,则输出-
例如,输入:
1 2 3
1 2 3 4 5
程序应该输出:
+ 0 + 0 -
再例如,输入:
1 4 5
10 11 12 13 15
程序应该输出:
0 - 0 + +
再例如,输入:
2 3 5
7 8 9 10 11
程序应该输出:
+ 0 0 0 0
【资源约定】
峰值内存消耗(含虚拟机)< 256M
CPU消耗 < 3000ms
请严格按要求输出,不要画蛇添足的打印类似“请您输入...”的多余内容。
所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
注意:不要使用package语句,不要使用jdk1.6及以上的版本特性
注意:主类的名称必须是Main 否则按无效代码处理。
解题思路:
本题属于典型的博弈类问题,求解本题时需要互换角色来思考,自己既是选手、又是对手,且要求都使用最聪明的方式来进行对弈,其实对于本题来说,进行五局比赛,其实就是一个对局循环了5次,我们只需要解出一个判断方法,那么无论是对于5局.10局都是可以的。所以求解的思路是:对n个球进行抓取,第一次我抓,第二次对手抓,但是在对手抓时,如何才能更聪明的抓取,这个时候我们就应该扮演成对手来抓球。直到最后剩下的球的数量不足以被抓取的时候本局结束,判断谁获胜即可。
答案源码:
public class Year2016_Bt9 { static int [] getArr = new int[3]; //每次可取数目 static int [] initArr = new int [5]; //5局的初始球数 // static char ans; public static void main(String[] args) { Scanner scanner = new Scanner(System.in); for (int i = 0; i < 3; i++) { getArr[i] = scanner.nextInt(); } for (int i = 0; i < 5; i++) { initArr[i] = scanner.nextInt(); } Arrays.sort(getArr);//对可抽取个数的数组进行排序 for (int i = 0; i < 5; i++) { char ans = f(initArr[i],0,0); System.out.print(ans + " "); } } private static char f(int n, int a1, int a2) { //如果当前剩余的球小于最小的取球数,出口 if (n<getArr[0]) { if((a1%2)==1&&(a2%2)==0) return '+'; else if((a1%2)==0&&(a2%2)==1) return '-'; else return '0'; } boolean isPing = false; //记录是否平局 for (int i = 0; i < 3; i++) { //只有当剩余的球数大于等于要抽取的球数的时候,才能进行抽取 if (n>=getArr[i]) { char res = f(n-getArr[i], a2, a1+getArr[i]); if (res=='-') return '+'; if(res=='0') isPing = true; } } if (isPing) { //如果当前是平局,返回0 return '0'; }else { return '-'; } } }
输出样例:
其中有不足或者改进的地方,还希望小伙伴留言提出,一起学习!
感兴趣的小伙伴可以关注专栏!
灰小猿陪你一起进步!