博弈论入门
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
模型
有两堆各若干个物品,两个人轮流从某一堆或同时从两堆中取同样多的物品,规定每次至少取一个,多者不限,最后取光者得胜。
思路
以上是关于博弈论入门的主要内容,如果未能解决你的问题,请参考以下文章