Nim博弈和威佐夫博弈 Return of the Nim
来源:互联网 发布:avsow永久域名 编辑:程序博客网 时间:2024/06/01 16:03
Nim博弈
Nim游戏的概述:
还记得这个游戏吗?给出n列珍珠,两人轮流取珍珠,每次在某一列中取至少1颗珍珠,但不能在两列中取。最后拿光珍珠的人输。
后来,在一份资料上看到,这种游戏称为“拈(Nim)”。据说,它源自中国,经由被贩卖到美洲的奴工们外传。辛苦的工人们,在工作闲暇之余,用石头玩游戏以排遣寂寞。后来流传到高级人士,则用便士(Pennies),在酒吧柜台上玩。
最有名的玩法,是把十二枚便士放成3、4、5三列,拿光铜板的人赢。后来,大家发现,先取的人只要在3那列里取走2枚,变成了1、4、5,就能稳操胜券了,游戏也就变得无趣了。于是大家就增加列数,增加铜板的数量,这样就让人们有了毫无规律的感觉,不易于把握。
直到本世纪初,哈佛大学数学系副教授查理士•理昂纳德•包顿(Chales Leonard Bouton)提出一篇极详尽的分析和证明,利用数的二进制表示法,解答了这个游戏的一般法则。
一般规则是规定拿光铜板的人赢。
Nim游戏的数学理论论述:
Nim游戏是博弈论中最经典的模型,它又有着十分简单的规则和无比优美的结论Nim游戏是组合游戏(Combinatorial Games)的一种,准确来说,属于“Impartial Combinatorial Games”(以下简称ICG)。满足以下条件的游戏是ICG(可能不太严谨):1、有两名选手;2、两名选手交替对游戏进行移动(move),每次一步,选手可以在(一般而言)有限的合法移动集合中任选一种进行移动;3、对于游戏的任何一种可能的局面,合法的移动集合只取决于这个局面本身,不取决于轮到哪名选手操作、以前的任何操作、骰子的点数或者其它什么因素; 4、如果轮到某名选手移动,且这个局面的合法的移动集合为空(也就是说此时无法进行移动),则这名选手负。根据这个定义,很多日常的游戏并非ICG。例如象棋就不满足条件3,因为红方只能移动红子,黑方只能移动黑子,合法的移动集合取决于轮到哪名选手操作。
通常的Nim游戏的定义是这样的:有若干堆石子,每堆石子的数量都是有限的,合法的移动是“选择一堆石子并拿走若干颗(不能不拿)”,如果轮到某个人时所有的石子堆都已经被拿空了,则判负(因为他此刻没有任何合法的移动)。
这游戏看上去有点复杂,先从简单情况开始研究吧。如果轮到你的时候,只剩下一堆石子,那么此时的必胜策略肯定是把这堆石子全部拿完一颗也不给对手剩,然后对手就输了。如果剩下两堆不相等的石子,必胜策略是通过取多的一堆的石子将两堆石子变得相等,以后如果对手在某一堆里拿若干颗,你就可以在另一堆中拿同样多的颗数,直至胜利。如果你面对的是两堆相等的石子,那么此时你是没有任何必胜策略的,反而对手可以遵循上面的策略保证必胜。如果是三堆石子……好像已经很难分析了,看来我们必须要借助一些其它好用的(最好是程式化的)分析方法了,或者说,我们最好能够设计出一种在有必胜策略时就能找到必胜策略的算法。
对于第三条,我们有更进一步的定义Position,我们将Position分为两类:
P-position:在当前的局面下,先手必败。
N-position:在当前的局面下,先手必胜。
他们有如下性质:
1.合法操作集合为空的局面是P-position;
2.可以移动到P-position的局面是N-position;
3.所有移动都只能到N-position的局面是P-position。
重要结论:对于一个Nim游戏的局面(a1,a2,...,an),它是P-position当且仅当a1^a2^...^an=0,其中^表示异或(xor)运算。
Nim游戏的形象具体论述:
as + bs + … + ms 是偶数
a1 + b1 + … + m1 是偶数
a0 + b0 + … + m0是偶数
23 = 822 = 421 = 220 = 1大小为7的堆0111大小为9的堆1001大小为12的堆1100大小为15的堆1111
由Nim取子游戏的平衡条件可知,此游戏是一个非平衡状态的取子游戏,因此,游戏人I在按获胜策略进行取子游戏下将一定能够取得最终的胜利。具体做法有多种,游戏人I可以从大小为12的堆中取走11枚硬币,使得游戏达到平衡(如下表)
23 = 822 = 421 = 220 = 1大小为7的堆0111大小为9的堆1001大小为12的堆0001大小为15的堆1111
归根结底,Nim取子游戏的关键在于游戏开始时游戏处于何种状态(平衡或非平衡)和第一个游戏人是否能够按照取子游戏的获胜策略来进行游戏。
例题1
[hihoCoder] 博弈游戏·Nim游戏
描述
今天我们要认识一对新朋友,Alice与Bob。
Alice与Bob总是在进行各种各样的比试,今天他们在玩一个取石子的游戏。
在这个游戏中,Alice和Bob放置了N堆不同的石子,编号1..N,第i堆中有A[i]个石子。
每一次行动,Alice和Bob可以选择从一堆石子中取出任意数量的石子。至少取1颗,至多取出这一堆剩下的所有石子。
Alice和Bob轮流行动,取走最后一个石子的人获得胜利。
假设每一轮游戏都是Alice先行动,请你判断在给定的情况下,如果双方都足够聪明,谁会获得胜利?
提示:Nim?!
输入
第1行:1个整数N。表示石子堆数。1≤N≤100
第2行:N个整数,第i个整数表示第i堆石子的个数A[i],1≤A[i]≤10000
输出
第1行:1个字符串,若Alice能够获胜输出"Alice",否则输出"Bob"
- 样例输入
33 2 1
- 样例输出
Bob
Nim游戏是经典的公平组合游戏(ICG),对于ICG游戏我们有如下定义:
1、两名选手;
2、两名选手轮流行动,每一次行动可以在有限合法操作集合中选择一个;
3、游戏的任何一种可能的局面(position),合法操作集合只取决于这个局面本身;局面的改变称为“移动”(move)。
4、若轮到某位选手时,该选手的合法操作集合为空,则这名选手判负。
对于第三条,我们有更进一步的定义Position,我们将Position分为两类:
P-position:在当前的局面下,先手必败。
N-position:在当前的局面下,先手必胜。
他们有如下性质:
1.合法操作集合为空的局面是P-position;
2.可以移动到P-position的局面是N-position;
3.所有移动都只能到N-position的局面是P-position。
对于一个局面,当且仅当A[1] xor A[2] xor ... xor A[N] = 0时,该局面为P局面
代码如下:
#include<cstdio>#include<iostream>#include<cstring>using namespace std;int main(){ int n; int a,p; while(scanf("%d",&n)!=EOF) { for(int i=0;i<n;i++) { scanf("%d",&a); if(i==0) p=a; else p^=a; } if(p==0) cout<<"Bob"<<endl; else cout<<"Alice"<<endl; } return 0;}
威佐夫博弈
问题:首先有两堆石子,博弈双方每次可以取一堆石子中的任意个,不能不取,或者取两堆石子中的相同个。先取完者赢。
解决思路:A:设(ai,bi)(ai ≤bi ,i=0,1,2,…,n)表示两堆物品的数量并称其为局势,如果甲面对(0,0),那么甲已经输了,这种局势我们称为奇异局势。前几个奇异局势是:(0,0)、(1,2)、(3,5)、(4,7)、(6,10)、(8,13)、(9,15)、(11,18)、(12,20)。任给一个局势(a,b),如下公式判断它是不是奇异局势: ak =[k(1+√5)/2],bk= ak + k (k=0,1,2,…,n 方括号表示取整函数)。
判断是否为奇异局势的代码如下
#include<cstdio>#include<iostream>#include<cmath>using namespace std;#define P sqrt(5.0)int main(){ int a,b,t; while(scanf("%d",&a,&b)!=EOF) { if(a>b) { t=a; a=b; b=a; } t=b-a; if(a==(int)(t*(1+P)/2))///奇异局势 printf("为奇异局势"); } return 0;}如果为奇异局势,则先手必输。
Problem Description
Sherlock and Watson are playing the following modified version of Nim game:
- There are n piles of stones denoted as ,,...,, and n is a prime number;
- Sherlock always plays first, and Watson and he move in alternating turns. During each turn, the current player must perform either of the following two kinds of moves:
- Choose one pile and remove k(k >0) stones from it;
- Remove k stones from all piles, where 1≤k≤the size of the smallest pile. This move becomes unavailable if any pile is empty.
- Each player moves optimally, meaning they will not make a move that causes them to lose if there are still any better or winning moves.
Giving the initial situation of each game, you are required to figure out who will be the winner
Input
The first contains an integer, g, denoting the number of games. The 2×g subsequent lines describe each game over two lines:
1. The first line contains a prime integer, n, denoting the number of piles.
2. The second line contains n space-separated integers describing the respective values of ,,...,.
- 1≤g≤15
- 2≤n≤30, where n is a prime.
- 1≤pilesi≤ where 0≤i≤n−1
- Output
For each game, print the name of the winner on a new line (i.e., either "
Sherlock
" or "Watson
")Example Input
232 3 222 1
Example Output
题目分析:当n=2的时候用威佐夫博弈,当n>=3时用Nim博弈。SherlockWatson
#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#include <cmath>using namespace std;int a[1000];int main(){ int t; scanf("%d",&t); while(t--) { int n; scanf("%d",&n); for(int i=0; i<n; i++) { scanf("%d",&a[i]); } if(n==2)///等于2时为威佐夫博弈 { if(a[0]<a[1]) { int t=a[0]; a[0]=a[1]; a[1]=t; } if(floor((a[0]-a[1])*((sqrt(5.0)+1.0)/2.0))!=a[1])//威佐夫博弈的核心判断公式 { printf("Sherlock\n"); } else { printf("Watson\n"); } } else///大于等于3时用尼姆博弈 { int k=a[0]; for(int i=1; i<n; i++) { k^=a[i]; } if(k==0) { printf("Watson\n"); } else { printf("Sherlock\n"); } } } return 0;}
- Nim博弈和威佐夫博弈 Return of the Nim
- 省SD2017 A Return of the Nim【威佐夫博弈+NIM】
- Return of the Nim----Nim博弈+威佐夫博弈 山东省第八届省赛A题
- 山东省第八届省赛 Return of the Nim(博弈)
- SDUT 3893 (山东省第八届ACM省赛A题) Return of the Nim 博弈nim+威佐夫
- 2017 省赛 山东 A Return of the Nim 【博弈】【Nim+Wythoff】
- 2017第八届浪潮杯山东省赛 A.Return of the Nim 博弈
- Return of the Nim----博弈(2017山东ACM-ICPC省赛)
- 巴什博弈+威佐夫博弈+Nim博弈
- nim 博弈
- Nim博弈
- Nim博弈
- NIM 博弈
- Nim 博弈
- Nim博弈
- nim 博弈
- Nim博弈
- Nim博弈
- [来源未知]卡片游戏
- [GNU/Linux] Linux系统调用-线程相关(一):基本知识
- 将某一线程设置为后台线程
- 昂贵的聘礼 POJ
- poj 2001 Shortest Prefixes (Trie树)
- Nim博弈和威佐夫博弈 Return of the Nim
- 码力训练
- API学习ArrayList
- 使用druid连接池带来的坑testOnBorrow=false
- JSP无法连接mysql数据库,使用java可以连接
- netty客户端引发的线程血案(一)
- 2台电脑共享硬盘方法 有时候我们需要在两台电脑之间传送大容量的文件,例如系统备份的镜像文件,或者要拷贝整个硬盘里的文件,我们又找不到这么大的移动存储设备,该怎么办,其实在没有网络和大容量移动磁盘的情
- c++笔记1
- DOM小结