2016蓝桥杯"取球博弈"问题
较难,网上有能得出正确结果的代码,但是读了一下,像是拼凑出的结果,逻辑不通,代码和注释不符
参考网上代码写了一版,结构相对清晰,注释比较详细
题目很长:
两个人玩取球的游戏。
一共有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
package ah;
import java.util.Arrays;
import java.util.Scanner;
// 输入3个数,表示可取球的数目{n1,n2,n3}
// 输入5局总球数{x1 x2 ... x5}
// 持有奇数个球的一方获胜
// 输出:先取球者的结果(+:能赢 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
public class 取球博弈 {
// 持有奇数个球的一方获胜
static boolean isOdd(int num) {
return num % 2 == 1 ? true : false;
}
// (+:能赢 0:能平 -:必输)
static void showRersult(int _1的球, int _2的球) {
String RET_WIN_ = "+ ";
String RET_LOSE = "- ";
String RET_TIE_ = "0 ";
if (isOdd(_1的球) && !isOdd(_2的球)) {
System.out.print(RET_WIN_);
} else if (!isOdd(_1的球) && isOdd(_2的球)) {
System.out.print(RET_LOSE);
} else if (isOdd(_1的球) && isOdd(_2的球)) {
System.out.print(RET_TIE_);
} else {
System.out.print(RET_TIE_);
}
}
// 不够取:false
// 够取:true
static boolean isNotEnough(int _剩下的球, int _要取得球) {
if (_剩下的球 < _要取得球) {
return true;
} else {
return false;
}
}
static void getInput() {
Scanner sc = new Scanner(System.in);
for (int i = 0; i < 3; i++) {
_arr_n[i] = sc.nextInt();
}
for (int i = 0; i < 5; i++) {
_arr_x[i] = sc.nextInt();
}
sc.close();
}
// java中方法参数传递方式是按值传递
// 基本类型:传递的是基本类型的字面量值的拷贝
// 引用类型:传递的是该参量所引用的对象在堆中地址值的拷贝
// 所以参数[_取到的球数]在方法内的修改,方法外是得不到的,必须使用返回值
public static int getBall(int i_N, int _取到的球数) {
boolean _getted = false;
for (int j = _arr_n.length - 1; j >= 0; j--) {
// 取球,往多了取,如可取{1,2,3},先取3
boolean b奇奇得偶 = (isOdd(_取到的球数) && isOdd(_arr_n[j]));
boolean b偶偶得偶 = (!isOdd(_取到的球数) && !isOdd(_arr_n[j]));
if (b奇奇得偶 || b偶偶得偶) {
// 已经有奇数,还取奇数?不行(取了不就偶数了么?)
// 已经有偶数,还取偶数?不行(取了不就偶数了么?)
continue;
}
if (isNotEnough(_arr_x[i_N], _arr_n[j])) {
// 剩余的球<可取的最小数:结束
continue;
}
_取到的球数 += _arr_n[j];
_arr_x[i_N] -= _arr_n[j];
_getted = true;
break;
}
if (!_getted) {
// 如果上述方法没有取到, 取出一个最大的数
for (int j = _arr_n.length - 1; j >= 0; j--) {
if (isNotEnough(_arr_x[i_N], _arr_n[j])) {
continue;
}
_取到的球数 += _arr_n[j];
_arr_x[i_N] -= _arr_n[j];
}
}
return _取到的球数;
}
// 取球博弈(ball game playing)
static void ballGamePlaying() {
// 输入{取法}和{初始球数}
// {可取}按升序排列
Arrays.sort(_arr_n);
// 计算每一局
for (int i_N = 0; i_N < _arr_x.length; i_N++) {
int _1的球 = 0, _2的球 = 0;
while (true) {
if (isNotEnough(_arr_x[i_N], _arr_n[0])) {
// 剩余的球<可取的最小数:结束
break;
}
_1的球 = getBall(i_N, _1的球);
_2的球 = getBall(i_N, _2的球);
}
// 一局结束,输出结果
showRersult(_1的球, _2的球);
}
}
// 能取球数:可取球的数目{n1,n2,n3}
static int[] _arr_n = new int[3];
// 每一局的初始球数:输入5局总球数{x1 x2 ... x5}
static int[] _arr_x = new int[5];
public static void main(String[] args) {
testCase123();
ballGamePlaying();
System.out.println();
System.out.println("+ 0 + 0 -:标准答案");
testCase145();
ballGamePlaying();
System.out.println();
System.out.println("0 - 0 + +:标准答案");
testCase235();
ballGamePlaying();
System.out.println();
System.out.println("+ 0 0 0 0:标准答案");
getInput();
ballGamePlaying();
}
static void testCase123() {
_arr_n[0] = 1;
_arr_n[1] = 2;
_arr_n[2] = 3;
for (int i = 0; i < 5; i++) {
_arr_x[i] = i + 1;
}
}
static void testCase145() {
_arr_n[0] = 1;
_arr_n[1] = 4;
_arr_n[2] = 5;
for (int i = 0; i < 5; i++) {
_arr_x[i] = i + 10;
}
_arr_x[4] = 15;
}
static void testCase235() {
_arr_n[0] = 2;
_arr_n[1] = 3;
_arr_n[2] = 5;
for (int i = 0; i < 5; i++) {
_arr_x[i] = i + 7;
}
}
}
结果:
+ 0 + 0 -
+ 0 + 0 -:标准答案
0 - 0 + +
0 - 0 + +:标准答案
+ 0 0 0 0
+ 0 0 0 0:标准答案
2016蓝桥杯"取球博弈"问题的更多相关文章
- java实现第七届蓝桥杯取球博弈
题目9.取球博弈 取球博弈 两个人玩取球的游戏. 一共有N个球,每人轮流取球,每次可取集合{n1,n2,n3}中的任何一个数目. 如果无法继续取球,则游戏结束. 此时,持有奇数个球的一方获胜. 如果两 ...
- 2012年第三届蓝桥杯C/C++程序设计本科B组省赛 取球博弈
2012年第三届蓝桥杯C/C++程序设计本科B组省赛 取球博弈 题目描述 **取球博弈 今盒子里有n个小球,A.B两人轮流从盒中取球,每个人都可以看到另一个人取了多少个,也可以看到盒中还剩下多少个,并 ...
- java算法 第七届 蓝桥杯B组(题+答案) 9.取球博弈
9.取球博弈 (程序设计) 两个人玩取球的游戏.一共有N个球,每人轮流取球,每次可取集合{n1,n2,n3}中的任何一个数目.如果无法继续取球,则游戏结束.此时,持有奇数个球的一方获胜.如果两人都是 ...
- java实现取球博弈
今盒子里有n个小球,A.B两人轮流从盒中取球,每个人都可以看到另一个人取了多少个,也可以看到盒中还剩下多少个,并且两人都很聪明,不会做出错误的判断. 我们约定: 每个人从盒子中取出的球的数目必须是:1 ...
- 【2016蓝桥杯省赛】试题C++ B组试题
一. 煤球数目 作答:171700 #include <iostream> using namespace std; int main() { ,x=; ;i<=;i++){ ...
- 蓝桥杯T37(nim博弈)
题目链接:http://lx.lanqiao.cn/problem.page?gpid=T37 题意:中文题诶- 思路:nim博弈 个人感觉这题最难的地方是将题目转换为博弈模型,如果能将之转换为博弈模 ...
- 2017蓝桥杯取位数(C++B组)
题目: 标题:取数位求1个整数的第k位数字有很多种方法.以下的方法就是一种.// 求x用10进制表示时的数位长度 int len(int x){ if(x<10) return 1; retur ...
- Java实现第八届蓝桥杯取数位
取数位 求1个整数的第k位数字有很多种方法. 以下的方法就是一种. 还有一个答案:f(x/10,k--) public class Main { static int len(int x){ // 返 ...
- HDU - 2689 Sort it与2016蓝桥杯B 交换瓶子 排序(相邻交换与任意交换)
Sort it You want to processe a sequence of n distinct integers by swapping two adjacent sequence ele ...
随机推荐
- Spring4.x Jpa + hibernate的配置(废弃JpaTemplate)
近年来 ORM(Object-Relational Mapping,对象关系映射,即实体对象和数据库表的映射)技术市场热闹非凡,各种各样的持久化框架应运而生,其中影响最大的是 Hibernate 和 ...
- css animate
AniX https://a-jie.github.io/AniX/
- css3实现条纹以及方格斜纹背景
CSS代码: .stripes { height: 250px; width: 375px; float: left; margin: 10px; -webkit-background-size: 5 ...
- mysql 两张表的数据设置主外健关联删除
image_group 主表 image 副表 alter table image add constraint fk_group_idforeign key (group_id)references ...
- asd短片数篇
黄乙己 黄乙己是站着AK而正常的唯一的人.他身材挺高大:蜡黄脸色,眼角间时常夹着些饼干屑:一副黑色的眼镜.虽然挺正常,可是他有良好的饮食习惯,似乎十多个月都是吃的牛奶泡饭,也没有洗饭盒.他对人说话,总 ...
- L1-043 阅览室
天梯图书阅览室请你编写一个简单的图书借阅统计程序.当读者借书时,管理员输入书号并按下S键,程序开始计时:当读者还书时,管理员输入书号并按下E键,程序结束计时.书号为不超过1000的正整数.当管理员将0 ...
- 学习笔记CB004:提问、检索、回答、NLPIR
聊天机器人,提问.检索.回答. 提问,查询关键词生成.答案类型确定.句法和语义分析.查询关键词生成,提问提取关键词,中心词关联扩展词.答案类型确定,确定提问类型.句法和语义分析,问题深层含义剖析.检索 ...
- postgresql 最大连接数相关
PG中有一张表记录着当前有多少连接 表名:pg_stat_activity 查询当前连接数: select count(1) from pg_stat_activity; 查询最大连接数 show m ...
- 用js简单实现一下迪克斯特拉算法
今天看书看到了迪克斯特拉算法,大概用js实现一下呢,计算最短路径. 首先,迪克斯特拉算法只适用于有向无环图,且没有负权重,本例关系图如下哦,数字为权重,emmmm,画得稍微有点丑~ //大概用js实现 ...
- 【linux日常】 ACL权限管理
ACL ((Access Control Lists) setfacl命令 这里引用一个非常详细的命令介绍. 要点: getfacl -R 递归获取acl权限,可以存储为文件以备还原 g ...