【每日蓝桥】42、一六年省赛Java组真题“取球博弈”

218 阅读3分钟

这是我参与更文挑战的第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 '-';
		}
		
	}

}

输出样例:

​​​​

其中有不足或者改进的地方,还希望小伙伴留言提出,一起学习!

感兴趣的小伙伴可以关注专栏!

灰小猿陪你一起进步!