三大经典博弈 尼姆博奕 + 巴仕博弈 + 威佐夫博弈 +SG函数

第一,尼姆博奕(Nimm Game)

一,特例分析

有三堆各若干个物品,两个人轮流从某一堆取任意多的

物品,规定每次至少取一个,多者不限,最后取光者得胜。

我们用(a,b,c)表示某种局势,首先(0,0,0)显然是奇异局势,无论谁面对奇异局势,都必然失败。

第二种奇异局势是(0,n,n),只要与对手拿走一样多的物品,最后都将导致(0,0,0)。

 任何奇异局势(a,b,c)都有a^b^c =0。

如果我们面对的是一个非奇异局势(a,b,c),要如何变为奇异局势呢? 只要将其中一个是

变成其他两个数的异或就行了。

二,例题

题目1:今有若干堆火柴,两人依次从中拿取,规定每次只能从一堆中取若干根,可将一堆全取走,但不可不取,

最后取完者为胜,求必胜的方法。 

 备注: 若所有火柴数异或为0,则该状态被称为利他态,用字母T表示;否则, 为利己态,用S表示。

[定理1]:对于任何一个S态,总能从一堆火柴中取出若干个使之成为T态。

[定理2]:T态,取任何一堆的若干根,都将成为S态。

[定理 3]:S态,只要方法正确,必赢。

[定理4]:T态,只要对方法正确,必败。

题目2:今有若干堆火柴,两人依次从中拿取,规定每次只能从一堆中取若干根,可将一堆全取走,但不可不取,

最后取完者为负,求必胜的方法。 

备注:若一堆中仅有1根火柴,则被称为孤单堆。若大于1根,则称为充裕堆。0:没有富裕堆,1:有一个富裕堆  ,

 2:有大于等于个富裕堆

[定理1]:T2态必输。

[定理2]:S0 即仅有奇数个孤单堆,必败,T0  态必胜。

[定理3]:S1态,只要方法正确,必胜

[定理4]:S2态,只要方法正确,必胜.  

四,一般情况

有N堆石子,其中第i堆有Pi颗石子,每次从某一堆里选出若干石子去掉(但不能不去石子),两人轮流取石,

谁不能继续取谁就输了。

备注: 若所有火柴数异或为0,则该状态被称为利他态,用字母T表示;否则, 为利己态,用S表示。

若只有一堆石子,为T状态

若有m堆石子,每堆有k颗石子, m堆为奇数时 ,为T状

定理:
   对于一个局面,令H=P1^P2^P3^… ^Pn。若H=0则为T局面,否则为s局面

总结:

 有n堆各若干个物品,两个人轮流从某一堆取任意多(或者最多m个,只需把每堆%m)的物品,规定每次至少

取一个,多者不限,最后取光者得胜。  把每堆数量求异或a1^a2^...^ai'^...^an,结果为零则先手必输,否则必赢

三,Nim问题的扩展
问题:取石子问题
    有N堆石子,其中第i堆有Pi颗石子,每次去掉某一堆里最多m棵石子(m>0),两人轮流取石,

谁不能继续取谁就输了。什么情况下先手必胜,什么情况下后手必胜?

解析:

    将P1,P2,P3, … Pn 对m+1求余得到q1,q2,q3, …,qn然后符合定理一的结果,记H=q1^q2^q3^ …^qn 。

若H=0则为T局面,否则为s局面。

备注: s: 为利己态,先手必胜,非奇异态。

              T:为利他态,先手必败,奇异态。

四,Nimk问题的取石子方法
问题:取石子问题
    有N堆石子,其中第i堆有Pi颗石子,每次可以从最多K堆中选出若干石子去掉(但不能不去石子),

两人轮流取石,谁不能继续取谁就输了。

什么情况下先手必胜,什么情况下后手必胜?

K=1,为Nim问题。

对于K>1的情况,我们令把P1~Pn这n个数,转成二进制,然后每位分别相加,每位最后结果mod (K+1)即可。

如果每一位结果都是0,则为T局面,否则是s局面


第二:Sprague-Grundy函数(SG函数)

一,概述:

如果我们把游戏中的某一个局面看作一个顶点,把局面之间的转换用边来表示,

那么很多游戏都可以转化成图游戏模型。图游戏模型 给定有向无环图G=(V,E)和一个起始点,

双方轮流行动。每个人每次可以从当前点出发沿着一条有向边走到另外一个点。谁无法走了谁就输。

一些图游戏可以通过Sprague-Grundy函数来判定先手的胜负情况(简称SG函数)。

SG函数 一个图G=(V,E)的SG函数g,是定义在v上的一个非负整数函数:

g(x)=min{key>=0 | key≠g(y) for <x,y>∈E}

key属于[0,n](n为顶点个数)

如果x的出度为0,那么g(x)=0。(边界条件)

g(x)就是x的后继点的SG值中没有出现过的最小值

解析:

这样定义有什么好处呢?我们把一个图的当前状态值定义为游戏者处在的这个点的SG值。

如果游戏者处在一个点x,g(x)≠0。那么0, 1, …, g(x)-1这些数必然都出现在x的后继节点的SG值中

而游戏者可以走到这些点中的任意一个。也就是说:游戏者可以通过一步走棋把图的当前状态值任意的减小

(当然必须保证状态值始终>=0)。如果游戏者处在一个点x,g(x)=0。那么游戏者无论如何移动,

下一个点的SG值都不等于0。

定理:

   对于一个图游戏,如果图的当前状态等于0,那么先手必败,否则必胜。

扩展:

   多图游戏 有多个图,每个图都有一个当前节点。两个游戏者轮流行动。每个人每次可以把某一个图中的

当前节点沿着该点连出的有向边移动到另一个点。无法移动的那个人输。

结论:

   设这些图的当前状态值分别是a1, a2, …, ak,如果:a1 ^ a2 ^ … ^ ak = 0,那么先手必败,否则必胜。

三,定理

1、 所有终结点都是必败点P

2、所有一步能走到必败点P的就是N点;

3、通过一步操作只能到N点的就是P点;


第三:巴仕博弈(Bash Game)

一,题目:

  只有一堆n个物品,两个人轮流从这堆物品中取物,规 定每次至少取一个,最多取m个。最后取光者得胜。

二,分析

1,如果n=m+1,那么由于一次最多只能取m个,所以,无论先取者拿走多少个,

后取者都能够一次拿走剩余的物品,后者取胜。必败

2,法则:如果n=(m+1)*r+s,(r为任意自然数,s≤m),那么先取者要拿走s个物品,如果后取者拿走k(≤m)个,

那么先取者再拿走m+1-k个,结果剩下(m+1)(r-1)个,以后保持这样的取法,那么先取者肯定获胜。

总之,要保持给对手留下(m+1)的倍数,就能最后获胜。必胜局

3,备注:

P点:即必败点,某玩家位于此点,只要对方无失误,则必败;

N点:即必胜点,某玩家位于此点,只要自己无失误,则必胜。


第四:威佐夫博弈(Wythoff Game)

一,题目

有两堆各若干个物品,两个人轮流从某一堆或同时从两堆中取同样多的物品,规定每次至少取一个,

多者不限,最后取光者得胜

二,解析

1,。我们用(a[k],b[k])(a[k] ≤ b[k] ,k=0,1,2,...,n)表示两堆物品的数量并称其为局势。

2,如果甲面对(0,0),那么甲已经输了,这种局势我们称为奇异局势。

3,奇异局(举例)

首先列举人们已经发现的前几个奇异局势:(0,0)、(1,2)、(3,5)、(4,7)、(6,10)

(8,13)、(9,15)、(11,18)、(12,20)。

通过观察发现:a[0]=b[0]=0,a[k]是未在前面出现过的最小自然数,而 b[k]= a[k] + k。

4,奇异局势有如下三条性质:

1)任何自然数都包含且仅包含在一个奇异局势中。

2)任意操作都可以使奇异局势变为非奇异局势。

3)必有一种操作可以使非奇异局势变为奇异局势。

5,奇异局势公式:

a[k]=[k*(1+√5)/2],b[k]=a[k]+k。

(k=0,1,2......,[ ]表示取整)

有趣的是,式中的(1+√5)/2正是黄金分割比例。

6,判断

可以看出,如果两人都采取正确的操作,那么对于非奇异局势,先拿者必胜,对于奇异局势,

先拿者必败。


第五,SG函数模板

//模板:(SG函数)
int f[N],sg[N],hash[N];     
void getSG(int n)
{
    int i,j;
    memset(sg,0,sizeof(sg));
    for(i=1;i<=n;i++)
    {
        memset(hash,0,sizeof(hash));
        for(j=1;f[j]<=i;j++)
            hash[sg[i-f[j]]]=1;
        for(j=0;j<=n;j++)    
        {
            if(hash[j]==0)
            {
                sg[i]=j;
                break;
            }
        }
    }
}

第六,威佐夫博弈模板

//威佐夫博弈模板
#include <stdio.h>
#include <math.h>
const double Gsr=(1+sqrt(5.0))/2;
void swap(int &a,int &b)
{
    int t=b;
    b=a;
    a=t;
}
int main()
{
    int a,b;
    while(~scanf("%d%d",&a,&b))
    {
        if(a>b)
            swap(a,b);
        if(a == (int)(Gsr*(b-a))) //奇异局势,先拿者输
            puts("First Lose");
        else
            puts("First Win");
    }
    return 0;
}






阅读更多
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/yu_zhi_bo_zhi_shui/article/details/47829713
文章标签: dp 算法 poj
个人分类: 博弈论
上一篇poj3254 Corn Fieldsdp 状态压缩
下一篇hdu 1074 Doing Homework 压缩dp
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭