1254: 盒子游戏(Java)
WUSTOJ 1254: 盒子游戏
参考博客
叶剑飞Victor的博客
盒子游戏——爱程序网
原理是从上面博客看的,我另外补充了几幅图,方便理解
Description
有两个相同的盒子,其中一个装了n个球,另一个装了一个球。Alice和Bob发明了一个游戏,规则如下:Alice和Bob轮流操作,Alice先操作。每次操作时,游戏者先看看哪个盒子里的球的数目比较少,然后清空这个盒子(盒子里的球直接扔掉),然后把另一个盒子里的球拿一些到这个盒子中,使得两个盒子都至少有一个球。如果一个游戏者无法进行操作,他(她)就输了。下图是一个典型的游戏:
面对两个各装一个球的盒子,Bob无法继续操作,因此Alice获胜。你的任务是找出谁会获胜。假定两人都很聪明,总是采取最优策略。
Input
输入最多包含300组测试数据。每组数据仅一行,包含一个整数n(2<=n<=10^9)。输入结束标志为n=0。
Output
对于每组数据,输出胜者的名字。
Sample Input
2
3
4
0
Sample Output
Alice
Bob
Alice
题目分析
n=2时,Alice(A)拿完球后,只能得到(1,1)这种情况,结果A赢。
n=3时,A先拿,只能得到(2,1),Bob(B)再拿,只能得到(1,1),结果B赢。
n=4时,A一定会将球分成(3,1),B只能将球分成(2,1),A只能将球分成(1,1),结果A赢。
n=5时,A一定会将球分成(3,2),B只能将球分成(2,1),A只能将球分成(1,1),结果A赢。
n=6时,A一定会将球分成(3,3),B只能将球分成(2,1),A只能将球分成(1,1),结果A赢。
n=7时,无论A将球分成多少,B一定会将球分成(3,k)(k=1,2,3),A只能将球分成(2,1),B只能将球分成(1,1),结果B赢。(WPS流程图有限制。。。不规范的是我用图片编辑补充的。)
结论1:当球的个数为(m,n)且满足1<=n<=m,m=2k-1(k=1,2,3,4,…)时,当前拿球的人一定会输。
由于Alice先拿球,我们可以这么理解,如果Alice不能将球分成结论1
的情况,那么Bob一定会将球分成结论1
的情况,从而导致自己输掉。
由于Alice先拿球,可以进一步将结论分成2个:
1、球的个数为
结论1
所示,Alice一定会输;
2、球的个数不为结论1
所示,Alice都可以将球分成结论1
所示,Alice一定会赢。
这里有必要说明一点,拿球结果只和球较多的那部分有关,较少的部分最终都会被扔掉,不必考虑。不明白就多看几遍上面的图并自行体会。
这里我们只需要证明第1条(即结论1)成立,第2条自然也就成立。下面就用数学归纳法
来证明第1条是否成立:
解:
第一步,当k1=1时,盒子状态为(1,1),当前是Alice拿,因此Alice输;
第二步,当k2=k1+1时,盒子状态为(3,1),当前是Alice拿,因此Alice输;
第三步,令k=e时,球的状态为(2e-1,1)时,满足结论1
,当前是Alice拿,因此Alice输;
当k=e+1时,球的状态为(2e+1-1,1),
Alice只能分成(m,n),且1<=n<=m,m+n=2e+1-1,
那么m的范围是[2e,2e+1-2],(与此对应的n的范围是[2e-1,1]),
因此可以看出m是大于k=e时的球个数2e-1的
也就是说,Alice是不可能将球的个数分成(2e-1,1)的,接下来Bob肯定将球分成(2e-1,1)从而让Alice拿,也就是让Alice输。
因此当k=e时,能够使k=e+1满足结论1
,因此,结论1
成立。结论得证。
代码
分析:当n=2k-1时,n的二进制是前面一串0,最后k个1
,
因此n&1
只有2种情况1和0
,如果是1,将n右移1位;如果是0,退出右移循环。
此时判断n是否等于0,等于0说明n=2k-1,那么Alice输
不等于0,说明n最后一位的左边还有1,而最后一位是0,显然与开头说的最后k个1
中的最后
相矛盾,那么Alice赢。
// 这是参考博客的第一个的方法
// 提交用时:349ms
import java.util.Scanner;
public class Main {
private Scanner sc;
private int n;
public Main() {
sc = new Scanner(System.in);
n = sc.nextInt();
while(0 != n) {
while((n & 1) == 1) {
n >>= 1;
}
if(0 == n) {
System.out.println("Bob");
} else {
System.out.println("Alice");
}
n = sc.nextInt();
}
sc.close();
}
public static void main(String[] args) {
new Main();
}
}
分析:既然我们已经知道了Bob赢时的n值,那为何我们不将这些n值先算出来呢,再同输入的值相比较,这样对于数据较多(此题明确说了最多300组数据)时,肯定会缩短计算时间的。
// 这是参考博客的第二个的方法
// 提交用时:256ms
import java.util.Scanner;
public class Main {
private Scanner sc;
private int n, i;
private int[] bob; // 使得Bob赢的n值
public Main() {
sc = new Scanner(System.in);
bob = new int[32];
bob[0] = 1;
for(i = 1; i <= 31; i++) {
bob[i] = bob[i - 1] * 2 + 1;
}
n = sc.nextInt();
while(0 != n) {
for(i = 1; i <= 31; i++) {
if(n == bob[i]) {
System.out.println("Bob");
break;
} else if(n < bob[i]) {
System.out.println("Alice");
break;
}
}
n = sc.nextInt();
}
sc.close();
}
public static void main(String[] args) {
new Main();
}
}
1254: 盒子游戏(Java)的更多相关文章
- ACM: NBUT 1107 盒子游戏 - 简单博弈
NBUT 1107 盒子游戏 Time Limit:1000MS Memory Limit:65535KB 64bit IO Format: Practice Appoint ...
- 盒子游戏(The Seventh Hunan Collegiate Programming Contest)
盒子游戏 有两个相同的盒子,其中一个装了n个球,另一个装了一个球.Alice和Bob发明了一个游戏,规则如下:Alice和Bob轮流操作,Alice先操作.每次操作时,游戏者先看看哪个盒子里的球的数目 ...
- NBUT 1107——盒子游戏——————【博弈类】
盒子游戏 Time Limit:1000MS Memory Limit:65535KB 64bit IO Format: Submit Status Practice NBUT 110 ...
- 俄罗斯方块游戏 --- java
俄罗斯方块游戏 如有疑问请查看:http://zh.wikipedia.org/zh-tw/%E4%BF%84%E7%BD%97%E6%96%AF%E6%96%B9%E5%9D%97 更多疑问请参考: ...
- 生命游戏 Java
本程序由四个类组成:其中Init_data,用于初始化各个活细胞的状态judge_state,用于判断下一代的细胞状态,并进行更新.set_color,用于给GUI界面中各个细胞涂色set_frame ...
- 猜字游戏java
一.实践目的 1.掌握基本输入输出. 2.掌握方法定义与调用,理解参数传递方式. 3.掌握数组的声明.定义与初始化,数组的处理. 4.掌握数组作为方法参数和返回值. 二.实践要求 利用方法.数组.基本 ...
- 人机猜拳游戏Java
作业要求: 我的代码: package day20181119;/** * 猜拳游戏 * @author Administrator * @version1.0 */import java.util. ...
- 算法笔记_179:历届试题 数字游戏(Java)
目录 1 问题描述 2 解决方案 1 问题描述 问题描述 栋栋正在和同学们玩一个数字游戏. 游戏的规则是这样的:栋栋和同学们一共n个人围坐在一圈.栋栋首先说出数字1.接下来,坐在栋栋左手边的同学要 ...
- 21点游戏java实现
21点的基本知识 21点是世界上比较流行的扑克游戏项目 除掉大小王的一副扑克牌,共计52张牌 21点不区分花色,其中A----10均代表扑克牌本身的点数J Q K代表10点 区分庄家和闲家,其中闲家可 ...
随机推荐
- P5658 括号树
P5658 括号树 题解 太菜了啥都不会写只能水5分数据 啥都不会写只能翻题解 题解大大我错了 我们手动找一下规律 我们设 w[ i ] 为从根节点到结点 i 对答案的贡献,也就是走到结点 i ,合 ...
- OpenJudge计算概论-整数的个数
/*========================================================== 整数的个数 总时间限制: 1000ms 内存限制: 65536kB 描述 给定 ...
- word中英文双引号的样式区分与替换技巧
https://jingyan.baidu.com/article/3f16e003147ea42590c10349.html 场景:一篇word文档中,想要全选更改字体,使得中文全部为“宋体”,英文 ...
- log4j.xml简单配置实现在控制台打印sql执行语句【加注释】
转: log4j.xml简单配置实现在控制台打印sql执行语句 2017年09月27日 13:02:34 艾然丶 阅读数 8804 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协 ...
- 运行时给java对象动态的属性赋值
运行时给java对象动态的属性赋值 如何给java对象动态的属性赋值(也就是在代码执行的时候才决定给哪个属性赋值) 1.自定义一个工具类ReflectHelper,代码如下所示: pa ...
- HTTP和WSGI协议
HTTP协议简介 超文本传输协议(HyperText Transfer Protocol)是一种应用层协议.HTTP是万维网的数据通信的基础.设计HTTP最初的目的是为了提供一种发布和接收HTML页面 ...
- SpringCloud学习成长之 十 高可用服务注册中心
文章 第一篇: 服务的注册与发现(Eureka) 介绍了服务注册与发现,其中服务注册中心Eureka Server,是一个实例,当成千上万个服务向它注册的时候,它的负载是非常高的,这在生产环境上是不太 ...
- java通过telnet远程至windows机器执行dos命令
准备工作,远程windows机器中开启telnet服务,将远程登录用户添加至telnetClients用户组 核心代码: import java.io.IOException; import java ...
- preg_replace修饰符e的用法
$tmp_refer = postget('refer');$tmp_refer = preg_replace("/tn-(.*?).html/ies", "'tn-'. ...
- cursor -- 定义鼠标样式
cursor -- 定义鼠标样式 取值: [ [<uri> ,]* [ auto | crosshair | default | pointer | move | e-resize | n ...