蓝桥杯 取球博弈

取球博弈

两个人玩取球的游戏。
一共有N个球,每人轮流取球,每次可取集合{n1,n2,n3}中的任何一个数目。
如果无法继续取球,则游戏结束。
此时,持有奇数个球的一方获胜。
如果两人都是奇数,则为平局。

假设双方都采用最聪明的取法,
第一个取球的人一定能赢吗?
试编程解决这个问题。

输入格式:
第一行3个正整数n1 n2 n3,空格分开,表示每次可取的数目 (0<n1,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


  首先声明,本人也是刚刚接触算法的菜鸟一枚,这篇文章紧紧是在学习之路上的笔记,不作为标准。

  刚看到这道题也是没有头绪,然后参考各路大神解题思想,代码思路个人想法,未能优化。

  思路:

     1.  为保证手上的球数为奇数个,则奇数次取球时首要想法是取奇数个,可取集合中的奇数不符合剩余球数时取偶数个。偶数次取球时则首要想法取偶数个,可取集合中的偶数不符合剩余球数时取奇数个。

     2.  保证手上为奇数的情况下,每次取球取满足要求的最大值,以压缩对手的可取空间。

import java.util.Scanner;

public class t9 {

	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		
		int[] a = new int[3];//可取集合
		a[0] = in.nextInt();
		a[1] = in.nextInt();
		a[2] = in.nextInt();
		
		int[] b = new int[5];//5局,每局初始球数
		b[0] = in.nextInt();
		b[1] = in.nextInt();
		b[2] = in.nextInt();
		b[3] = in.nextInt();
		b[4] = in.nextInt();
		
		for(int j = 0;j<b.length;j++){  //5局,循环5次
			System.out.println("第"+j+"局");
			int i = 1;  //用作while循环标记
			int m1 = 1; //表示1号选手第m1次取球,初始为1
			int m2 = 1; //表示2号选手第m2次取球,初始为1
			int sum1 = 0; //记录1号每次取球后的总球数
			int sum2 = 0; //记录2号每次取球后的总球数
			int k = b[j]; //K用于记录每次取球后剩余的球数,当前为初始化
			while(k>=a[0]){ //只要剩余球数大于或等于每次可取球数的最低数,就循环。
				if(i%2 == 1){ //如果为奇数,则表示1号选手取球,否则为2号选手
					System.out.println("  1号选手");
					if(m1 % 2 == 1){ //判断1号选手是奇数次取球,是则首要先取奇数个球
						System.out.println("    1号选手第"+m1+"次");
						boolean flag1 = false;
						for(int x = a.length-1;x>=0;x--){ //从大到小遍历,取可选集合中的最大奇数个球
							if(a[x]%2 == 1 && a[x]<=k){ //判断是否为奇数且小于或等于剩余球数
								sum1 += a[x];  //总球数增加
								System.out.println("      1号取"+a[x]);
								k = k-a[x];   //剩余球数减少
								flag1 = true; //能取到奇数个球
								break; //结束遍历
							}
						}
						if(!flag1){  //如果不能取到奇数个球,则取偶数个球
							for(int y = a.length-1;y>=0;y--){
								if(a[y]%2 == 0 && a[y]<=k){
									sum1 += a[y];
									System.out.println("      1号取"+a[y]);
									k = k-a[y];
									break;
								}
							}
						}
					}else{ //如果为第偶数次取球,则首要是取偶数个球,保证手上的球数为奇数
						System.out.println("    1号选手第"+m1+"次");
						boolean flag1 = false; 
						for(int y = a.length-1;y>=0;y--){ //遍历可取集合的偶数,满足条件则本次取球结束
							if(a[y]%2 == 0 && a[y]<=k){
								sum1 += a[y];
								System.out.println("      1号取"+a[y]);
								k = k-a[y];
								flag1 = true;
								break;
							}
						}
						if(!flag1){  //如未能取偶数个球,则取奇数个球
							for(int x = a.length-1;x>=0;x--){
								if(a[x]%2 == 1 && a[x]<=k){
									sum1 += a[x];
									System.out.println("      1号取"+a[x]);
									k = k-a[x];
									flag1 = true;
									break;
								}
							}
						}
					}
					m1++;  //1号选手第m1次取球加一
				}else{  //2号选手类推
					System.out.println("  2号选手");
					if(m2 % 2 == 1){
						System.out.println("    2号选手第"+m2+"次");
						boolean flag1 = false;
						for(int x = a.length-1;x>=0;x--){
							if(a[x]%2 == 1 && a[x]<=k){
								sum2 += a[x];
								System.out.println("      2号取"+a[x]);
								k = k-a[x];
								flag1 = true;
								break;
							}
						}
						if(!flag1){
							for(int y = a.length-1;y>=0;y--){
								if(a[y]%2 == 0 && a[y]<=k){
									sum2 += a[y];
									System.out.println("      2号取"+a[y]);
									k = k-a[y];
									break;
								}
							}
						}
					}else{
						System.out.println("    2号选手第"+m2+"次");
						boolean flag1 = false; 
						for(int y = a.length-1;y>=0;y--){
							if(a[y]%2 == 0 && a[y]<=k){
								sum2 += a[y];
								System.out.println("      2号取"+a[y]);
								k = k-a[y];
								flag1 = true;
								break;
							}
						}
						if(!flag1){
							for(int x = a.length-1;x>=0;x--){
								if(a[x]%2 == 1 && a[x]<=k){
									sum2 += a[x];
									System.out.println("      2号取"+a[x]);
									k = k-a[x];
									flag1 = true;
									break;
								}
							}
						}
						
					}
					m2++;
				}
				i++; //循环标记
			}//while
			System.out.println("sum1="+sum1+"  sum2="+sum2);
			if(sum1%2==1 && sum2%2==0){
				System.out.println("+");
			}else if(sum1%2==0 && sum2%2==1){
				System.out.println("-");
			}else{
				System.out.println("0");
			}
		}//for
	}//main

}//class

输出格式并未符合题目输出要求,打印内容紧紧是为了了解程序思路。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值