取石子游戏详解NIM
取石子游戏详解NIM
目录(?)[+]
http://blog.csdn.net/pipisorry/article/details/39249337
取石子游戏详解NIM
取石子游戏详解NIM
取石子游戏详解NIM
取石子游戏详解NIM
取石子游戏详解NIM
取石子游戏是一个古老的博弈游戏,发源于中国,它是组合数学领域的一个经典问题。它有许多不同的玩法,基本上是两个玩家,玩的形式是轮流抓石子,胜利的标准是抓走了最后的石子。
玩家设定: 先取石子的是玩家A,后取石子的是玩家B。
经典的三种玩法:
一、巴什博奕(Bash Game),有1堆含n个石子,两个人轮流从这堆物品中取物,规定每次至少取1个,最多取m个。取走最后石子的人获胜。
二、尼姆博奕(Nimm Game),有k堆各n个石子,两个人轮流从某一堆取任意多的物品,规定每次至少取一个,多者不限。取走最后石子的人获胜。
三、威佐夫博奕(Wythoff Game),有2堆各n个石子,两个人轮流从某一堆或同时从两堆中取同样多的物品,规定每次至少取1个,多者不限。取走最后石子的人获胜。POJ1067
平衡状态的概念:
引入一个概念,平衡状态,又称作奇异局势。当面对这个局势时则会失败。任意非平衡态经过一次操作可以变为平衡态。每个玩家都会努力使自己抓完石子之后的局势为平衡,将这个平衡局势留给对方。因此,玩家A能够在初始为非平衡的游戏中取胜,玩家B能够在初始为平衡的游戏中取胜。
玩法一(1堆n个石子每次最多取m个):
即,若n=k*(m+1),则后取着胜,反之,存在先取者获胜的取法。n%(m+1)==0. 先取者必败。
这个游戏还可以有一种变相的玩法:两个人轮流报数,每次至少报一个,最多报十个,谁能报到100者胜。(<=>从一堆100个石子中取石子,最后取完的胜)
最后一个奇异局势是n=(0)。一种奇异局势是,n=(m+1),那么无论我取走多少个,对方都能够一次取走剩余所有的物品取胜。
一般的奇异局势是n=(m+1)*i,其中i为自然数,即n%(m+1)=0,面对这种情况无论我怎么取,对方总可以将其恢复为n%(m+1)=0,一直到n=(m+1)局势。
就是把当前面对的非奇异局势变为奇异局势留给对方。如果当前的石子个数为(m+1)*i+s,那么就将s个石子取走,使其达到奇异局势。
玩法二(k堆石子每次只从1堆取):
简化问题:有三堆各若干个物品,两个人轮流从某一堆取任意多的物品,规定每次至少取一个,多者不限,最后取光者得胜。
拓展: 任给N堆石子,两人轮流从任一堆中任取(每次只能取自一堆),取最后一颗石子的人获胜,问先取的人如何获胜?
根据上面所述,N个数异或即可。如果开始的时候T=0,那么先取者必败,如果开始的时候T>0,那么只要每次取出石子使得T=0,即先取者有获胜的方法。
最后一个奇异局势是(0,0...,0)。另一个奇异局势是(n,n,0...0),只要对手总是和我拿走一样多的物品,最后会面对(0,0...,0)。
从二进制位的角度上说,奇异局势时,每一个bit位上1的个数都是偶数。
玩法三(2堆石子每次从一或两堆取一样数目的石子):
前几个奇异局势是:(0,0)、(1,2)、(3,5)、(4,7)、(6,10)、(8,13)、(9,15)、(11,18)、(12,20)。。。
从如上性质可知,两个人如果都采用正确操作,那么面对非奇异局势,先拿者必胜;反之,则后拿者取胜。
Ak = [k*(1+sqrt(5.0)/2]
Bk = Ak + k
其中k=0,1,2,...,n ,方括号表示int取整函数。
有了这个通项式子,逆向的,对于某一个局势,只需要判断其A是否是黄金分割数的某个k的倍数,然后再确认B是否等于A+k即可。
奇妙的是其中出现了黄金分割数(1+√5)/2 = 1.618...,因此,由ak,bk组成的矩形近似为黄金矩形,由于2/(1+√5)=(√5-1)/2,可以先求出j=[a(√5-1)/2],若a=[j(1+√5)/2],那么a = aj,bj = aj + j,若不等于,那么a = aj+1,bj+1 = aj+1+ j + 1,若都不是,那么就不是奇异局势。然后再按照上述法则进行,一定会遇到奇异局势。
我们会发现这个序列的规律,设序列第k个奇异局势元素为(Ak,Bk),k为自然数。那么,初始条件k=0时是,A0=B0=0,递推关系为下一个奇异局势的Ak是未在前面出现过的最小自然数,且Ak = Bk + k。
变种玩法:“皇后登山”游戏,在空的围棋棋盘上放一个棋子,该棋子每次只能向上或向右或沿对角线向右上方向移动(相似国际象棋),可以移动任意格,但不能不移动,两人轮流移动棋子,先将棋子移动到右上角者赢,问先移棋者的必胜策略。《智力游戏中的数学方法》
code:
- /****************************************************************************/
- /* 编程之美 - NIM捡石子问题 皮皮 2014-9-10 */
- /****************************************************************************/
- #include <assert.h>
- #include <stdio.h>
- #include <math.h>
- /* 黄金分割数最优算法 */
- static int nim(int x, int y){
- double a = (sqrt(5.0) + 1) / 2; //goldenNum 1.618...
- int n = abs(x - y); //bn - an
- x = x < y? x : y; //取小者
- return ( x != int(a * n) );
- }
- int main(){
- int x, y;
- while(scanf("%d%d", &x, &y) == 2)
- printf("%d\n", nim(x, y));
- return 0;
- }
拓展:?
【综合一、三】
任给N堆石子,两人轮流从任一堆中任取(每次只能取自一堆),规定每方每次最多取K颗,取最后一颗石子的一方获胜.问先取的人如何获胜?
与上面的问题比,这个更复杂一些,我们可以这样做
令Bi=Ai mod(K+1)
定义T‘=B1 xor B2 xor ... xor Bn
如果T‘=0 那么没有获胜可能,先取者必败
如果T’>0 那么必然存在取的方法,使得T‘=0,先取者有获胜的方法
假设对方取了在Ai中取了r<=K个
如果Ai中剩下的石子多于K 那么就在Ai中取走K+1-r个则Bi不变 T‘还是0
如果Ai<=K 那么我们需要重新计算Bi和T‘ 按照上面的方法来做就可以了
【其它类似题型】
POJ1740 A New Stone Game
MIPT 100 Nim Game -- who is the winner?
POJ 1704 Georgia and Bob
附:
1.Wythoff’s Game (威佐夫博弈)解释[类似解释亦可见于编程之美NIM(3)]
Wythoff's Nim
有两堆石子,不妨先认为一堆有10,另一堆有15个,双方轮流取走一些石子,合法的取法有如下两种:
1)在一堆石子中取走任意多颗;
2)在两堆石子中取走相同多的任意颗;
约定取走最后一颗石子的人为赢家,求必败态(必胜策略)。
这个可以说是MR.Wythoff(于1907年提出此游戏)一生全部的贡献。不知道高斯取整函数与Beatty定理,所做的只能是找规律而已。可以先在http://www.cut-the-knot.org/pythagoras/withoff.shtml玩几局。
简单分析一下,容易知道两堆石头地位是一样的,我们用余下的石子数(a,b)来表示状态,并画在平面直角坐标系上。
用定理: 有限个结点的无回路有向图有唯一的核 中所述的方法寻找必败态。先标出(0,0),然后划去所有(0,k),(k,0),(k,k)的格点;然后找y=x上方未被划去的格点,标出(1,2),然后划去(1,k),(k,2),(1+k,2+k),同时标出对称点(2,1),划去(2,k),(1,k),(2+k,1+k);然后在未被划去的点中在y=x上方再找出(3,5)。。。按照这样的方法做下去,如果只列出a<=b的必败态的话,前面的一些是(0,0),(1,2),(3,5),(4,7),(6,10),…
接下来就是找规律的过程了,忽略(0,0),记第n组必败态为(a[n],b[n])
命题一:a[n+1]=前n组必败态中未出现过的最小正整数
[分析]:如果a[n+1]不是未出现的数中最小的,那么可以从a[n+1]的状态走到一个使a[n+1]更小的状态,和我们的寻找方法矛盾。
命题二:b[n]=a[n]+n
[分析]:归纳法:若前k个必败态分别为 ,下证:第k+1个必败态为
从该第k+1个必败态出发,一共可能走向三类状态,从左边堆拿走一些,从右边堆拿走一些,或者从两堆中拿走一些.下面证明这三类都是胜态.
情况一:由命题一,任意一个比a[k+1]小的数都在之前的必败态中出现过,一旦把左边堆拿少了,我们只要再拿成那个数相应的必败态即可。
情况二(从右边堆拿走不太多):这使得两堆之间的差变小了,比如拿成了 ,则可再拿成 ;
情况二(从右边堆拿走很多):使得右边一堆比左边一堆更少,这时类似于情况一,比如拿成了 (其中a[m] ;
情况三:比如拿成 ,则可再拿成 .
综上所述,任何从 出发走向的状态都可以走回核中.故原命题成立.
以上两个命题对于确定(a[n],b[n])是完备的了,给定(0,0)然后按照这两个命题,就可以写出(1,2),(3,5),(4,7),…
这样我们得到了这个数列的递推式,以下我们把这两个命题当成是(a[n],b[n])的定义。
先证明两个性质:
性质一:核中的a[n],b[n]遍历所有正整数。
[分析]:由命题一,二可得a[n],b[n]是递增的,且由a[n]的定义显然。
性质二:A={a[n]:n=1,2,3,…},B={b[n]:n=1,2,3,…},则集合A,B不交。
[分析]:由核是内固集,显然。
实际上a[n]和b[n]就是一个Beatty序列。
(Betty 定理):如果存在正无理数 A, B 满足 1/A + 1/B = 1,那么集合 P = { [A*t], t ∈ Z+}、Q = { [B*t], t ∈ Z+} 恰为集合 Z+ 的一个划分,即:P ∪ Q = Z+,P ∩ Q = ø。证明见附录2。
考虑到Betty定理中“恰为Z+的划分”这一说,这意味着,Z+中的每个数都恰好出现一次,与上述矩阵的性质十分吻合。
于是我们猜想每一行第一列的数满足 [Φi] 的形式,得到每一行第二列的数为 [Φi] + i = [Φi + i] = [(Φ + 1)i]
我们的目的是要让 Z+ 中每个数都在这个矩阵中出现,于是考虑到 Betty 定理的条件,Φ 和 (Φ + 1) 应满足 1/Φ + 1/(Φ + 1) = 1。解这个方程,我们得到 Φ = (sqrt(5) + 1) / 2,于是 Φ + 1 = (sqrt(5) + 3) / 2。 ,到此,我们找到了该必败态的通项公式。
实际上这组Beatty序列还有一些别的性质,比如当一个数是Fibonacci数的时候,另一个数也是Fibonacci数;而且两者的比值也越来越接近黄金比,这些性质在得到通项公式之后不难证明。
启示:首先用定理所说的方法找核,然后给出核的规律(递推,或是通项)并且证明。
最后附上一张对应的必败态图.
2.Betti theorem:
设a、b是正无理数且1/a+1/b=1。记P={[na]|n为任意的正整数},Q={[nb]|n为任意的正整数},([x]'指的是取x的整数部分)则P与Q是Z+的一个划分,即P∩Q为空集且P∪Q为正整数集合Z+。
证明:
因为a、b为正且1/a+1/b=1,则a、b>1,所以对于不同的整数n,[na]各不相同,类似对b有相同的结果。因此任一个整数至多在集合P或Q中出现一次。
* 现证明P∩Q为空集(反证法):假设k为P∩Q的一个整数,则存在正整数m、n使得[ma]=[nb]=k。即k < ma、nb<k+1,等价地改写不等式为
m/(k+1)< 1/a < m/k及n/(k+1)< 1/b < n/k。相加起来得 (m+n)/(k+1) < 1 < (m+n)/k,即 k < m+n < k+1。这与m、n为整数有矛盾,所以P∩Q为空集。
*现证明Z+=P∪Q;已知P∪Q是Z+的子集,剩下来只要证明Z+是P∪Q的子集。(反证法)假设Z+\(P∪Q)有一个元素k,则存在正整数m、n使得[ma]< k <[(m+1)a]、[nb]< k <[(n+1)b]。 由此得ma < k ≦[ (m+1)a]-1<(m+1)a -1(因为a是无理数),类似地有nb < k ≦[ (n+1)b]-1<(n+1)b -1。等价地改写为 m/k < 1/a < (m+1)/(k+1)及n/k < 1/b < (n+1)/(k+1)。两式加起来,得
(m+n)/k < 1 < (m+n+2)/(k+1),即m+n < k < k+1 < m+n+2。这与m, n, k皆为正整数矛盾。
所以Z+=P∪Q。
取石子游戏详解NIM相关推荐
- 博弈论之双人取数游戏详解
描述 有如下一个双人游戏:N(2 <= N <= 100)个正整数的序列放在一个游戏平台上,游戏由玩家1开始,两人轮流从序列的两端取数,取数后该数字被去掉并累加到本玩家的得分中,当数取尽时 ...
- 博弈论之取石子游戏的学习
以下内容来自转载: 博弈问题简介 所讨论的博弈问题满足以下条件: 玩家只有两个人,轮流做出决策 游戏的状态集有限,保证游戏在有限步后结束,这样必然会产生不能操作者,其输 对任何一种局面,胜负只决定于局 ...
- poj 1067 取石子游戏(博弈+威佐夫博奕(Wythoff Game))
取石子游戏 Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 29959 Accepted: 9818 Descriptio ...
- POJ1067 取石子游戏 跪跪跪,很好的博弈论
取石子游戏 Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 29951 Accepted: 9814 Descriptio ...
- HDU2516 取石子游戏【博弈】
取石子游戏 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Subm ...
- bzoj 1413: [ZJOI2009]取石子游戏(博弈+DP)
1413: [ZJOI2009]取石子游戏 Time Limit: 10 Sec Memory Limit: 162 MB Submit: 711 Solved: 470 [Submit][Sta ...
- BZOJ 1413: [ZJOI2009]取石子游戏 博弈+Dp
title BZOJ 1413 Description 在研究过Nim游戏及各种变种之后,Orez又发现了一种全新的取石子游戏,这个游戏是这样的: 有n堆石子,将这n堆石子摆成一排.游戏由两个人进行, ...
- Python Tkinter——数字拼图游戏详解版
Python Tkinter 实践系列--数字拼图游戏详解版 import random #Python中的random是一个标准库用于生成随机数.随机整数.还有随机从数据集取数据. import t ...
- OPJ-1067 取石子游戏 解题报告(数论) 取石子游戏,betty定理
连接--A - 取石子游戏 Time Limit:1000MS Memory Limit:10000KB 64bit IO Format:%I64d & %I64u Descrip ...
最新文章
- 编写测试用例的方法_适合小白的测试用例编写方法,一看就会!
- nodejs中的全局函数setTimeout/clearTimeout,setInterval/clearInterval,unref/ref
- 【OJ】OJ的介绍和常用OJ推荐
- 议rman的crosscheck和obsolete
- node版本查看管理工具
- 微软认真聆听了开源 .NET 开发社区的炮轰: 通过CLI 支持 Hot Reload 功能
- IDEA上Debug调试全流程
- .NetCore实践篇:成功解决分布式监控ZipKin聚合依赖问题(三)
- java 20段常用代码,你绝对用的到(二)
- 【博士后招聘】浙江大学杨杰课题组-医学AI/大数据分析/自然语言处理
- 更改计算机睡眠时间注册表,如何通过修改注册表开启/关闭系统休眠?
- uniapp手机号码正则验证
- PLSQL使用SYSTEM用户连接报错:ORA-01031: insufficient privileges
- “怎样解题”-第二部分:怎样题解——作者:波利亚
- Petalinux EMMC启动
- Ubuntu18.04-使用wine打开CAJ文件并解决乱码问题
- 小白也能看懂的手机配置攻略
- 创建一个网站需要多少预算?
- hiredis-vip
- 总结iPhone、iPad各机型对应的iOS 系统版本(最全)