博弈论

来源:互联网 发布:淘宝卖花苗靠谱店铺 编辑:程序博客网 时间:2024/05/02 04:54

一.巴什博奕(Bash Game):

首先我们来玩一个比较古老的报数游戏。AB一起报数,每个人每次最少报一个,最多报4个。轮流报数,看谁先报到30.

如果不知道巴什博弈的可能会觉得这个是个有运气成分的问题,但是如果知道的人一定知道怎样一定可以赢。

比如A先报数的话,那么B一定可以赢(这里假定B知道怎么正确的报数)

B可以这样报数,每次报5-k(A)个数,其中k(A)A报数的个数这样的话没一次

两人报完数之后会变成5 10 15 20 25 30这样是不是B一定会赢呢?是不是有一种被欺骗的感觉呢?好吧下面我们来看看这个原理。我们先看下一个一眼就能看出答案的例子 比如说我们报到5(4+1),每次报最多报4,最少报1.那么是不是后者一定可以赢呢?答案是肯定的。好了到这巴什博弈的精髓基本就OK了。

那么如果我们要报到n+1,每次最多报n,最少报1个的话,后者一定能够赢。

现在我们需要报数到n,而每次最多报数m,最少报数1.我们可以化成这样

n = k*(1+m)+r(0 <= r <= m)这样的话如果r不等于0那么先手一定会赢,为什么呢?首先先手报r,那么剩下k(1+m)个数,那么我们每次报数1+m-k(B)个数就一定能保证最后剩下1+m,那么就到了上面我们说的那个了,先手就一定会赢,如果r=0那么后手一定会赢,道理一样的。

到这巴什博弈也就介绍完了,知道这个道理之后我们也可以去骗小朋友了。-_-//

二.威佐夫博奕(Wythoff Game):

   这种博弈比前面一种要稍微复杂一点。我们来看下下面这个游戏。

   有两堆火柴棍,每次可以从某一堆取至少1根火柴棍(无上限),或者从两堆取相同的火柴棍数。最后取完的是胜利者。好了,如果你不知道这个博弈定理,对于小数目的火柴棍数,可能还能推出来,但是如果火柴棍数一多,就不行了。看了下面的这个介绍,你也会有一种被骗的感觉。

   首先我们知道两堆火柴是没有差别的,也就是说第一堆有a,第二堆有b根和第一堆有b,第二堆有a根是一样的结果。

   我们用一个二维的状态(a,b)来记录当前剩下的火柴数,表示第一堆剩下a根火柴,第二堆剩下b根火柴。同样我们假设两个人的编号是AB,且A先取。

那么如果某个人遇到了这样的状态(0,0)那么也就是说这个人输了。这样的状态我们叫做奇异状态,也可以叫做失败态。

那么接下来的几个失败态为(1,2),(3,5),(4,7),(6,10),(8,13)……

我们用a[i]表示失败态中的第一个,b[i]表示失败态中的第二个.(i0开始).

那么我们可以看到b[i] = a[i]+i;i >= 0,a[i]是前面的失败态中没有出现过的最小的整数

下面我们可以得到三个基本的结论。

  1.每个数仅包含在一个失败态中

  首先我们知道a[k]是不可能和前面的失败态中的a[i],b[i]重复的(这点由a[i]的得到可以知道)

b[k] = a[k]+k > a[k-1]+k>a[k-1]+k-1+1>a[k-1]+(k-1) = b[k-1]>a[k-1]这样我们知道每个数仅在一个失败态中。

  2.每个失败态可以转到非失败态。

 加入当前的失败态为(a,b),那么如果我们只在一堆中取的话,肯定会变成非失败态(这点由第一点可以保证),如果从两堆同时取的话,由于每个失败态的差是不一样的,所以也不可能得到一个失败态。也就是说一个失败态不管你怎么取,都会得到一个非失败态。

   3.每个非失败态都可以转到一个失败态

对于这个结论,首先我们要知到每个状态(a,b)要么a = a[i],要么b = b[i].(每个数都出现在一个失败态中),下面我们分两种情况来讨论

   I.a = a[i].如果b = a的话那么一次取完就变成了(0,0).如果b > b[i]的话,那么我们从第二堆中取走b-b[i]就变成了一个失败态。如果b < b[i].那么我们从两堆中同时取走a-a[b-a[i]]这样得到失败态(a[b-a[i]],a[b-a[i]]+b-a[i])(a[i] = a)

   II.b = b[i].如果a > a[i]那么我们从第一堆中取走a-a[i]根火柴.

              如果a < a[i].这里又分两种情况。第一是a = a[k](k < i)

那么我们从第二堆取走b - b[k]就行了。

第二是a = b[k]这样的话由于两堆火柴是没有区别的,所以我们把b变成a[k]就行了,也即是从第二堆火柴中取走b - a[k]就变成了失败态

至于怎么判断一个状态是否是失败态.我们可以用下面的方法来判断(本人暂时还不会证明)

  a[i] = [i*(1+5)/2](这里的中括号表示向下取整)   b[i] = a[i]+i;

  那么这就是一个失败态

(三)尼姆博奕(Nimm Game):
有三堆各若干个物品,两个人轮流从某一堆取任意多的物品,规定每次至少取一个,多者不限,最后取光者得胜.
这种情况最有意思,它与二进制有密切关系,我们用(a,b,c)表示某种局势,首先(0,0,0)显然是奇异局势,无论谁面对奇异局势,都必然失
败.第二种奇异局势是(0,n,n),只要与对手拿走一样多的物品,最后都将导致(0,0,0).仔细分析一下,(1,2,3)也是奇异局势,无论对手如
何拿,接下来都可以变为(0,n,n)的情形.
计算机算法里面有一种叫做按位模2加,也叫做异或的运算,我们用符号xor表示这种运算.这种运算和一般加法不同的一点是1+1=0.先看
(1,2,3)的按位模2加的结果:
1 =二进制01
Xor 2 =二进制10
Xor 3 =二进制11 
———————
0 =二进制00 
对于奇异局势(0,n,n)也一样,结果也是0.
任何奇异局势(a,b,c)都有a xor b xor c =0。该结论可以推广至若干堆,都是成立的。
如果我们面对的是一个非奇异局势(a,b,c),要如何变为奇异局势呢?假设a < b< c,我们只要将c 变为a xor b,即可,因为有如下的运算
结果: a xor b xor (a xor b)=(a xor a) xor (b xor b)=0 xor 0=0.要将c 变为a xor b,只要从c中减去c-(a xor b)即可.
(四)Nim Staircase博奕:
这个问题是尼姆博弈的拓展:游戏开始时有许多硬币任意分布在楼梯上,共n阶楼梯从地面由下向上编号为0到n。游戏者在每次操作时
可以将楼梯j(1<=j<=n)上的任意多但至少一个硬币移动到楼梯j-1上。游戏者轮流操作,将最后一枚硬币移至地上(0号)的人获胜。
算法:将奇数楼层的状态异或,和为0则先手必败,否则先手必胜。证明略。
例题:Poj1704
这道题可以把两个棋子中间间隔的空格子个数作为一堆石子,则原题转化为每次可以把左边的一堆石子移到相邻的右边的一堆中。也就
是阶梯尼姆博弈,注意对输入数据先排序,然后倒着往前数(a[n]-a[n-1]-1为第一个),奇数个数到的就做一下xor,其中最前面的看
做a[1]-0-1,参考程序:
var t,n,b,i,j:longint; a:array[0..1000]of longint;begin readln(t); repeat dec(t); readln(n); for i:=1 to n do read(a[i]); qsort(1,n);//快排略 j:=0; b:=0; for i:=n downto 1 do begin inc(j); if odd(j) then b:=b xor (a[i]-a[i-1]-1); end; if b=0 then writeln('Bob will win') else writeln('Georgia will win'); until t=0;end.


原创粉丝点击