博弈论入门

Posted my-snowing

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了博弈论入门相关的知识,希望对你有一定的参考价值。

博弈论入门

博弈

巴什博弈 Bash Game

模型

只有一堆n个物品,两个人从轮流中取出(1~m)个;最后取光者胜。

思路

考虑到 若n=m+1 那么 第一个人不论如何取都不能取胜。

进一步我们发现 若 n=k*(m+1)+r; 先取者拿走 r 个,那么后者再拿(1~m)个

n=(k-1)*(m+1)+s; 先取者再拿走s 个 最后总能造成 剩下n=m+1 的局面。

因此,此时先手有必赢策略。相对应的,若n=k*(m+1) 那么先取者必输。

因此我们就可以写出对应程序(n,m>0)

int Bash_Game(int n,int m)//是否先手有必赢策略
{
    if (n%(m+1)!=0) return 1;
    return 0;
}

尼姆博弈 Nim Game

模型

当前有n堆每堆(M_i>0)个物品,两个人从轮流中取出若干个;最后取光者胜。

思路

从Bash Game中我们知道一个情形对应的一种状态,而从一个状态只能变成另一个状态时能很轻易的判定是否先手必胜

那么我们怎么把这样一个思想应用到Nim中呢

换句话说怎样才能在Nim中找到这样一个可以转化的状态

如果我们把n堆转化为n个整数,再将这n个整数用二进制表示,然后我们对这n个二进制数按位相加(不进位),若每一位相加都为偶数

那么我们称这个状态为偶状态,否则为奇状态;

可以证明:任何一个偶状态在其中一个数变小后一定会成为奇状态,一个奇状态一点可以通过改变一个数变为偶状态;

前一点很显然,因为一个数变小至少有一位发生变化,那么这一位就会改变原来的偶状态;

对于后一点,我们考虑一个从高位到低位某一位和为奇数的奇状态,必然有一个数的二进制此位为1,那么对于后面的较低位和为奇数的情况,只需要将这一位取反就可以得到一个偶状态;

那么现在我们就达到了成功的第一步——构造两个可以互相转化的状态并且显然存在奇状态为必胜态;偶状态为必败态;

那么我们对于n堆物品只需要判断他是否为奇状态就可以判定是否先手必胜;

但是对于每个数都二进制拆分非常麻烦,但是我们可以用神奇的位运算来完成这个过程

神奇的XOR与判断

如果有奇数个二进制数在第k为等于1那么显然在这一位上的和为奇数,同样的若有偶数个1则和为偶。

很明显位运算XOR满足我们的要求,偶数个1异或和为0,奇数个1异或和为1;

美滋滋这样不就搞完了

int Nimm_Game(int n)//假设n个数存在数组f[]中,有必胜策略返回1
{
    int flag=0;
    for(int i=1;i<=n;i++)
    flag^=f[i];
    if(flag) return 1;
    return 0;
}

一些小情况

但是当你遇到n非常大,并且每一堆的物品数是连续的整数的时候

我们就不能直接枚举n了

我们需要考虑连续非负整数的异或和问题

(f(x,y))(x)(y)的所有整数的异或和。

f[1,n]=f[0,n];

当存在(n=2^k-1)(,f(1,n)=f(0,n)=0,(kgeq2))

证明:

我们先来考虑(f(2^k,2^{k+1}-1))

(2^k)(2^{k+1}-1)(2^k)个数,最高位的一个数为(2^k)

若有(k>=1),则(2^k)为偶数,将这(2^k)个数的最高位去掉,异或和不变

因此(f(2^k,2^{k+1}-1)=f(2^k-2^k,2^{k+1}-2^k-1)=f(0,2^{k}-1))

因而存在(f(0,2^{k+1}-1)=f(0,2^k-1) xor f(2^k,2^{k+1}-1)=0)

(f(0,2^k-1)=0)

对于(,f(0,n),ngeq4)设n二进制表示的最高位1在第k位k>=2;

(f(0,n)=f(0,2^k-1) xor f(2^k,n)=f(2^k,n))

对于(2^k)(n)(n-2^k+1)个数,最高位共有(m=n-2^k+1)个1,去除最高位的1

当n为奇数时,m为偶数此时有(f(0,n)=f(2^k,n)=f(0,n-2^k)|2^k)

由于(n-2^k)与n奇偶性相同,递推上面的公式可得(f(0,n)=f(0,n-2^k-2^{k-1}-2^{k-2}cdots -2^2)=f(0,n\%4))

(n\%4=1)(f(0,n)=f(0,1)=1)

(n\%4=3)(f(0,n)=f(0,3)=0)

当n为偶数时,m为奇数,因而(f(0,n)=f(2^k,n)=f(0,n-2^k)xor2^k)

也相当于最高位不变,递推公式可得

(f(0,n)=f(0,n\%4)xor 2^kxor) (n[k]*2^k-1 xorcdots) (n[2]*2^2)

n[k]表示n的二进制表示的第k位

显然当n为偶数时 (f(0,n))的二进制从最高位到第3位和n的二进制表示相同

此时我们只需要判断第二位

(n\%4=0)(f(0,n)=n)

(n\%4=2)(f(0,n)=n+1)

综上所述:

[f(0,n)=f(1,n)egin{cases} n quad n\%4=01 quad n\%4=1\n+1 quad n\%4=2\0 quad n\%4=3\end{cases}]

代码给出来吧

//读入n,表示有从物品数分别1到n的n组物品,假设n个数存在数组f[]中
int xor_n(int n)//从1到n的异或和
{
     int t = n & 3;
     if (t & 1) return t / 2 ^ 1;
     return t / 2 ^ n;
}
int Nimm_Game(int n)//有必胜策略返回1
{
    int flag=0;
    for(int i=1;i<=n;i++)
    flag^=xor_n(f[i]);
    if(flag) return 1;
    return 0;
}

新Nim Game

在第一个回合中,第一个游戏者可以直接拿走若干个整堆的火柴。可以一堆都不拿,但不可以全部拿走。第二回合也一样,第二个游戏者也有这样一次机会。从第三个回合(又轮到第一个游戏者)开始,规则和Nim游戏一样。

如果你先拿,怎样才能保证获胜?如果可以获胜的话,还要让第一回合拿的火柴总数尽量小。

题解

我们第一次拿完后,要使得剩下的火柴中不存在异或和为0的子集,否则对方会将先手必败的状态留给我们。

所以我们可以使用贪心算法确定最优解。因此我们采用在线维护线性基的方法判断当前的数能否加入集合。


威佐夫博弈 Wythoff Game

模型

有两堆各若干个物品,两个人轮流从某一堆或同时从两堆中取同样多的物品,规定每次至少取一个,多者不限,最后取光者得胜。

思路

以上是关于博弈论入门的主要内容,如果未能解决你的问题,请参考以下文章

博弈论之入门小结

博弈论入门

博弈论经典入门

博弈论入门

博弈论(Game Theory)入门学习笔记(持续更新)

《博弈入门》第一章 引论