来自《编程之美》上的博弈问题。
题目是这样的。有M块石头和两个玩家A和B,玩家A先将石头分成若干堆,然后按照BABA.....的顺序不断轮流取石头,能将剩下的石头一次取光的玩家获胜。每次取石头时,每个玩家只能从若干堆石头任选一堆,取这一堆石头中任意数目(大于0)个石头。请问:玩家A要怎样分配和取石头才能保证自己有把握取胜?
分析与思考:我们可以将这个问题从最简单的情况逐渐复杂化分析,然后从中找出规律,然后再对所得规律加以证明。这样一个过程是分析问题解决问题的一种方式方法。
设N块石头堆,M块石头
接下来我们从N=1时开始分析,此时只有一堆石头,直接一次拿完,所以先手获胜。
N=2,M=2时,每堆石头各有一个石头。还是先手获胜。M>2时,对于(1,X)(X>1)情况,先手只要在X堆中拿走X-1个石头,这时情况转变为(1,1),最后还是先手获胜。对于(2,2),(3,3),(4,4)...(M/2,M/2)情况,都是后手获胜。因为不管先手从某一堆中拿走几个石头,都会引起两堆石头数量不平衡,而后后手都能把两堆石头数量变为相等(即为平衡),两堆石头相等后,如果(0,0),那么后手获胜。如果(x,x)(x>1),那么继续进行按照上述方法进行,可以看出两堆数量相等时,总是后手操作结果,不等时总是先手操作结果,并且先手没办法把两堆相等石头保持相等,因为一次只能改变一堆石头的数量。最后总是能得到(0,0)结果,所以后手总能·获胜。由此可以看出M为偶数时,只需将石头分成数量相等的两堆,后手必有方法获胜。
下面分析M为奇数时的情况,对于M=3,5,7时得出的结论是总是先手获胜。
那么这个结论到底正确与否?我们将证明这个结论。
《编程之美》只给出了结论。结论是假设我们把石头分解为N堆。那么对于奇数个石头总有XOR(M1,M2,...Mn)!=0。.........结论一
原因:如果M为奇数,那么转化成二进制,最后的二进制位一定为1,所以M1+M2+Mn=M,这些由0或1组成的Mi的最后一位的和总是1,那么根据二进制加法:1+1=原位变为0并且向前进一位,0+0=0原位还是0,1+0=1 原位变为1,所以可以推测M1,M2,...Mn这M个数最后一位1的个数总是奇数。只有奇数个1之和,取和之后最后一位才能变为1,从而满足最初M为奇数的设定。既然我们已经知道这被分解的M个数中的最后一位有奇数个1,那么我们做异或(异或和二进制求和类似,只是求和时需要进位而已)时,这M个数异或后,最后一位必为1,所以就有上述结论。
可以证明;当XOR(M1,M2,...Mn)!=0时,我们只需要改变某一个Mi的值。就可以让XOR(M1,M2...Mj...Mn)=0..............................结论二
原因:XOR!=0说明M1,M2,...Mn中必有某些位上在这M个数中该位的1的个数为奇数(比如101,011,111,每个数的第三位上1的总个数为3,而第1个数(101)的第2位为0,第2,3个数第2位均为1,那么这3个数第二位1的总个数就为2,以下分析都是根据这种分析得出的结论。),我们仅需将对应的某些奇数个1的位上的1的个数转变为偶数个1即可(某些位由0->1或1->0都可以实现某些位变为偶数个1,由于每个数都可以经过这样的变动,所以第二步关键是看数的选择。要求是选择一个经过这种改变后,改变后的数变小即可,),这样这M个数的每个位上都总共有偶数个1后,XOR=0。从而证明了结论二的正确性。
可以证明:当XOR(M1,M2,...Mn)=0时,我们总是只需要改变任何一个Mi的值,就可以让XOR(M1,M2...Mj...Mn)=0...............结论三
原因:XOR=0时,每一位上1的(对于这M个数来说)总个数都为偶数,所以改变其中任意一个数,都会引起某些位上的1的个数的增减,不管1的个数是增加1还是减少1,都会使某些位上1的个数变为奇数个,那么必有XOR≠0.从而证明了结论三的正确性。
最后总结:M为奇数时,无论怎样分堆,先手总是把这些堆石头的XOR设置为0,而后手总是素手无策的做出任何改变都不会把XOR设置为0,而最终只有XOR=0时才能获胜,所以总是先手赢。通过分析M个石头中每堆石头的数量的二进制位上,每位上1的总个数来得出上面三个结论不失为一种解决这个问题的方法。
以上红字和粗体字是我对《编程之美》石头游戏2中给出结论的证明与理解。
nim(2)“拈”游戏扩展问题分析
扩展问题:如果规定取反,取光所有石头的人输,又该如何控制局面?
可以参考:“拈”游戏扩展分析
这里我自己又想到一个题目的变形问题,假设玩家A分完石头,然后A先取石头,按照ABAB。。方式取石头,取光所有石头算输,情况又不大一样了。
设石头个数为N,
N为偶数时,N=2 玩家A不管如何分堆(2)或(1,1)都是A赢。
N=4,玩家A只需把石头分成(2,2),玩家A(A先取石头,A为先手)取一堆中的1块石头(或2块),B取走另外一堆的2块(或1块),这样还剩1块石头,A别无选择只得认输,B赢(后手赢)。
对于N≥4时,我们总有办法将石头分成2堆,一堆为2块石头,一堆为N-2块石头。这样A先取石头,可以取N-2的那一堆取到只剩2块石头为止,这样玩家B作为先手面对(2,2)情况(A作为后手),那么情况转为N=4,这样按照上面分析后手赢,所以作为后手的A,肯定赢。
另外N=1时,因为A先手,所以A输B赢。
N=3时,只要A把石头分成1+2或3+0即可赢。
所以只要N≠4或1,A作为先手并且给石头分堆,总有办法取胜。