初始博弈【二】Nim(hdu 1849,poj1704)
2016-05-20 13:25
411 查看
Nim
有n堆石子,每堆有ai颗石子,Alice和Bob轮流从非空的石子堆中取走至少一颗石子。Alice先取,去逛所有石子的一方获胜。当双方都采取最优策略时,谁会获胜?
1<=n<=1^6
1<=ai<=10^9
INPUT:
3
1 2 4
OUTPUT:
Alice
注意这个结论成立:
a1 XOR a2 XOR a3 XOR ……XOR an ≠ 0 ==> 必胜态
a1 XOR a2 XOR a3 XOR ……XOR an = 0 ==> 必败态
所以呢,非0则Alice获胜,为0则Bob获胜
《挑战程序》上的证明如下:
一旦从XOR为0的状态取走至少一颗石子,XOR就一定会变成非0。因此,可以证实必败之后肯定是必胜。
--------------------
观察XOR的二进制表示最高位的1,选取石子数的二进制表示对应位也为1的某堆石子。
只要从中取走使得该位变为0,且其余XOR中的1也反转的数量的石子,XOR就可以变成0。
同时,看了看这几篇博文感觉更加详细
http://blog.csdn.net/lgdblue/article/details/15809893 http://blog.csdn.net/acm_cxlove/article/details/7854530
第一个博客中的例子就很好理解^_^
核心代码:
hduoj1849
Total Submission(s): 3350 Accepted Submission(s): 2496
[align=left]Problem Description[/align]
大学时光是浪漫的,女生是浪漫的,圣诞更是浪漫的,但是Rabbit和Grass这两个大学女生在今年的圣诞节却表现得一点都不浪漫:不去逛商场,不去逛公园,不去和AC男约会,两个人竟然猫在寝食下棋……
说是下棋,其实只是一个简单的小游戏而已,游戏的规则是这样的:
1、棋盘包含1*n个方格,方格从左到右分别编号为0,1,2,…,n-1;
2、m个棋子放在棋盘的方格上,方格可以为空,也可以放多于一个的棋子;
3、双方轮流走棋;
4、每一步可以选择任意一个棋子向左移动到任意的位置(可以多个棋子位于同一个方格),当然,任何棋子不能超出棋盘边界;
5、如果所有的棋子都位于最左边(即编号为0的位置),则游戏结束,并且规定最后走棋的一方为胜者。
对于本题,你不需要考虑n的大小(我们可以假设在初始状态,棋子总是位于棋盘的适当位置)。下面的示意图即为一个1*15的棋盘,共有6个棋子,其中,编号8的位置有两个棋子。
大家知道,虽然偶尔不够浪漫,但是Rabbit和Grass都是冰雪聪明的女生,如果每次都是Rabbit先走棋,请输出最后的结果。
[align=left]Input[/align]
输入数据包含多组测试用例,每个测试用例占二行,首先一行包含一个整数m(0<=m<=1000),表示本测试用例的棋子数目,紧跟着的一行包含m个整数Ki(i=1…m; 0<=Ki<=1000),分别表示m个棋子初始的位置,m=0则结束输入。
[align=left]Output[/align]
如果Rabbit能赢的话,请输出“Rabbit Win!”,否则请输出“Grass Win!”,每个实例的输出占一行。
[align=left]Sample Input[/align]
2
3 5
3
3 5 6
0
[align=left]Sample Output[/align]
Rabbit Win!
Grass Win!
POJ1704
Georgia and Bob
Description
Georgia and Bob decide to play a self-invented game. They draw a row of grids on paper, number the grids from left to right by 1, 2, 3, ..., and place N chessmen on different grids, as shown in the following figure for example:
Georgia and Bob move the chessmen in turn. Every time a player will choose a chessman, and move it to the left without going over any other chessmen or across the left edge. The player can freely choose number of steps the chessman moves, with the constraint
that the chessman must be moved at least ONE step and one grid can at most contains ONE single chessman. The player who cannot make a move loses the game.
Georgia always plays first since "Lady first". Suppose that Georgia and Bob both do their best in the game, i.e., if one of them knows a way to win the game, he or she will be able to carry it out.
Given the initial positions of the n chessmen, can you predict who will finally win the game?
Input
The first line of the input contains a single integer T (1 <= T <= 20), the number of test cases. Then T cases follow. Each test case contains two lines. The first line consists of one integer N (1 <= N <= 1000), indicating the number of chessmen. The second
line contains N different integers P1, P2 ... Pn (1 <= Pi <= 10000), which are the initial positions of the n chessmen.
Output
For each test case, prints a single line, "Georgia will win", if Georgia will win the game; "Bob will win", if Bob will win the game; otherwise 'Not sure'.
Sample Input
Sample Output
棋盘游戏~
将棋子两两整体考虑,然后就可以转化成Nim啦~
【1】如果为偶数个棋子的话:两两之间的间隔作为每堆石子的个数。
将俩个里面右边的棋子左移->取石子。
将俩个里面左边的棋子左移.距离变大,石子增多,这里不同于Nim,但是再将右边的棋子左移就又变成Nim了,所以也不影响~
这样呢,所有的棋子之间的间隔变成0也就是取完了石子,达到必胜态。
间隔为0-->不管前面的棋子怎么动,只要挪动跟他成对的后面的那个棋子到相邻位置就好了。
---------------
【2】如果为奇数个棋子。设置一个坐标为0的就好了~
有n堆石子,每堆有ai颗石子,Alice和Bob轮流从非空的石子堆中取走至少一颗石子。Alice先取,去逛所有石子的一方获胜。当双方都采取最优策略时,谁会获胜?
1<=n<=1^6
1<=ai<=10^9
INPUT:
3
1 2 4
OUTPUT:
Alice
注意这个结论成立:
a1 XOR a2 XOR a3 XOR ……XOR an ≠ 0 ==> 必胜态
a1 XOR a2 XOR a3 XOR ……XOR an = 0 ==> 必败态
所以呢,非0则Alice获胜,为0则Bob获胜
《挑战程序》上的证明如下:
一旦从XOR为0的状态取走至少一颗石子,XOR就一定会变成非0。因此,可以证实必败之后肯定是必胜。
--------------------
观察XOR的二进制表示最高位的1,选取石子数的二进制表示对应位也为1的某堆石子。
只要从中取走使得该位变为0,且其余XOR中的1也反转的数量的石子,XOR就可以变成0。
同时,看了看这几篇博文感觉更加详细
http://blog.csdn.net/lgdblue/article/details/15809893 http://blog.csdn.net/acm_cxlove/article/details/7854530
第一个博客中的例子就很好理解^_^
核心代码:
int N; void solve(){ int x=0; for(int i=0;i<N;i++) x^A[i]; if(x!=0) puts("Alice"); else puts("Bob"); }
hduoj1849
Rabbit and Grass
Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 3350 Accepted Submission(s): 2496
[align=left]Problem Description[/align]
大学时光是浪漫的,女生是浪漫的,圣诞更是浪漫的,但是Rabbit和Grass这两个大学女生在今年的圣诞节却表现得一点都不浪漫:不去逛商场,不去逛公园,不去和AC男约会,两个人竟然猫在寝食下棋……
说是下棋,其实只是一个简单的小游戏而已,游戏的规则是这样的:
1、棋盘包含1*n个方格,方格从左到右分别编号为0,1,2,…,n-1;
2、m个棋子放在棋盘的方格上,方格可以为空,也可以放多于一个的棋子;
3、双方轮流走棋;
4、每一步可以选择任意一个棋子向左移动到任意的位置(可以多个棋子位于同一个方格),当然,任何棋子不能超出棋盘边界;
5、如果所有的棋子都位于最左边(即编号为0的位置),则游戏结束,并且规定最后走棋的一方为胜者。
对于本题,你不需要考虑n的大小(我们可以假设在初始状态,棋子总是位于棋盘的适当位置)。下面的示意图即为一个1*15的棋盘,共有6个棋子,其中,编号8的位置有两个棋子。
大家知道,虽然偶尔不够浪漫,但是Rabbit和Grass都是冰雪聪明的女生,如果每次都是Rabbit先走棋,请输出最后的结果。
[align=left]Input[/align]
输入数据包含多组测试用例,每个测试用例占二行,首先一行包含一个整数m(0<=m<=1000),表示本测试用例的棋子数目,紧跟着的一行包含m个整数Ki(i=1…m; 0<=Ki<=1000),分别表示m个棋子初始的位置,m=0则结束输入。
[align=left]Output[/align]
如果Rabbit能赢的话,请输出“Rabbit Win!”,否则请输出“Grass Win!”,每个实例的输出占一行。
[align=left]Sample Input[/align]
2
3 5
3
3 5 6
0
[align=left]Sample Output[/align]
Rabbit Win!
Grass Win!
#include <cstdio> int main(){ int n; while(scanf("%d",&n)!=EOF){ if(n==0) break; int ans=0,x; for(int i=0;i<n;i++){ scanf("%d",&x); ans^=x; } if(ans==0) puts("Grass Win!"); else puts("Rabbit Win!"); } return 0; }
POJ1704
Georgia and Bob
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 9007 | Accepted: 2899 |
Georgia and Bob decide to play a self-invented game. They draw a row of grids on paper, number the grids from left to right by 1, 2, 3, ..., and place N chessmen on different grids, as shown in the following figure for example:
Georgia and Bob move the chessmen in turn. Every time a player will choose a chessman, and move it to the left without going over any other chessmen or across the left edge. The player can freely choose number of steps the chessman moves, with the constraint
that the chessman must be moved at least ONE step and one grid can at most contains ONE single chessman. The player who cannot make a move loses the game.
Georgia always plays first since "Lady first". Suppose that Georgia and Bob both do their best in the game, i.e., if one of them knows a way to win the game, he or she will be able to carry it out.
Given the initial positions of the n chessmen, can you predict who will finally win the game?
Input
The first line of the input contains a single integer T (1 <= T <= 20), the number of test cases. Then T cases follow. Each test case contains two lines. The first line consists of one integer N (1 <= N <= 1000), indicating the number of chessmen. The second
line contains N different integers P1, P2 ... Pn (1 <= Pi <= 10000), which are the initial positions of the n chessmen.
Output
For each test case, prints a single line, "Georgia will win", if Georgia will win the game; "Bob will win", if Bob will win the game; otherwise 'Not sure'.
Sample Input
2 3 1 2 3 8 1 5 6 7 9 12 14 17
Sample Output
Bob will win Georgia will win
棋盘游戏~
将棋子两两整体考虑,然后就可以转化成Nim啦~
【1】如果为偶数个棋子的话:两两之间的间隔作为每堆石子的个数。
将俩个里面右边的棋子左移->取石子。
将俩个里面左边的棋子左移.距离变大,石子增多,这里不同于Nim,但是再将右边的棋子左移就又变成Nim了,所以也不影响~
这样呢,所有的棋子之间的间隔变成0也就是取完了石子,达到必胜态。
间隔为0-->不管前面的棋子怎么动,只要挪动跟他成对的后面的那个棋子到相邻位置就好了。
---------------
【2】如果为奇数个棋子。设置一个坐标为0的就好了~
#include <cstdio> #include <algorithm> #define maxn 10005 using namespace std; int P[maxn],n; void solve(){ if(n%2!=0){ //奇数 P[n++]=0; } sort(P,P+n); int ans=0; for(int i=1;i<n;i+=2){ ans^=(P[i]-P[i-1]-1); } if(ans==0) puts("Bob will win"); else puts("Georgia will win"); } int main(){ int T; scanf("%d",&T); while(T--){ scanf("%d",&n); for(int i=0;i<n;i++){ scanf("%d",&P[i]); } solve(); } return 0; }
相关文章推荐
- jQuery插件开发精品教程,让你的jQuery提升一个台阶
- 修改searchBar两种后背景颜色
- 基环内向树和基环外向树
- 常用的正则表达式---学习笔记(一)
- C++中对象或其对象指针的赋值
- ajax,php,jsp,ajax跨域调用
- AngularJS展示数据的ng-bind指令和{{}} 区别
- 手头软件产品的评价
- HTML地址栏(hash)获取并转码(个人菜鸟笔记)
- 安装node-sass时,遇到的错误MSBUILD: error MSB3428 Visual C++ VCBuild.exe 1) .NET Framework 2.0 SDK Microsoft
- php pdo链接mysql数据库
- Android逆向之旅---动态方式破解apk前奏篇(Eclipse动态调试smail源码)
- 五十七 POP3收取邮件
- cmake入门教程
- apache-tomcat-5.5.35.搭建实战
- python链接mysql数据库并以键值对的形式查询显示
- React入门实践之Todo List
- KMP算法简单实现
- 第一篇随笔
- iOS 图片轮播器