博弈论总结
开头&一些基本性质
本文的大部分内容来自于(YMD)的课件。((orz YMD))
一、必胜点和必败点
- (P)点:必败点,在双方都聪明无比的情况下(比如(zsy)和(ppl)在玩游戏),当前先手的人必败的情况。
- (N)点:必胜点,在双方操作都正确的情况下先手必胜的位置。
几个性质
- 所有的终止位置都是必败点(P)(我们认为这个是公理,即所有推导都在这个性质成立的基础上进行。
- 从任何一个必胜点(N)操作,至少有一种方法可以达到一个必败点(P)。
- 从一个必败点(P)出发,只能够到达一个必胜点(N)。
二、无偏博弈
无偏博弈是一类任意局势对于游戏双方都是平等的回合制双人游戏。平等的含义是当前的所有可行的走法仅仅只依赖与当前的局势,而与当前谁移动无关。换而言之,两个人除了先后手的区别之外就不存在任何区别。除此之外,还需要满足一下性质:
- 完全信息,任何一个游戏者都能够知晓整个游戏状态。
- 无随机行动,所有的行动都会转移到一个唯一确定的状态。
- 在有限步内游戏会终止,此时有唯一的胜者。
三、常见模型
- 巴什博奕((Bash Game))
- 威佐夫博弈((Wythoff Game))
- 尼姆游戏((Nim Game))
- (Anti-SG)游戏
- (Multi-SG)游戏
- (Every-SG)游戏
- 翻硬币游戏
- 树上删边游戏
巴什博奕((Bash Game))
基本问题
有一堆石子,总个数是(n),两名玩家轮流在石子堆中拿石子,每次至少取(1)个,至多取(m)个。取走最后一个石子的玩家为胜者。判定先手和后手谁胜。
解决方法
如果((m+1)|n)则先手必败,否则先手必胜。
证明:
假设((m+1)|n),那么假设先手拿走了(x)个,那么后手必定可以拿走((m+1)-x)个,这样子无论怎么拿,剩下的石头个数都将是(m+1)的倍数。那么最后一次取的时候石头个数必定还剩下(m+1)个,无论先手拿多少个,都会剩下石头,此时后手必定可以将剩下的所有石头取光从而获胜。
否则的话,先手可以取走模(m+1)余数个数个石头,此时模型转换为了先手面对((m+1)|n)个石头的情况,也就是后手必败,即先手必胜。
题目&代码
威佐夫博弈((Wythoff Game))
基本问题
有两堆石子,石子数可以不同。两人轮流取石子,每次可以在一堆中取,或者从两堆中取走相同个数的石子,数量不限,取走最后一个石头的人获胜。判定先手是否必胜。
解决方法
这个东西意义不是很大,打表找规律之后可以发现先手必败的状态一定形如(([i imesphi],[i imesphi^2]))。其中(phi=frac{sqrt{5}+1}{2}),([x])表示不大于(x)的最大整数。一些证明可以参考这个神仙博主的博客。
题目&模板
尼姆博弈((Nim Game))
基本问题
有三堆石子,两人轮流取,每次可以从一堆中取走任意数量个石子,至少取走一个,问先后手谁胜。
一般推广:有(n)堆石子(x_1,x_2,x_3,...,x_n),两人轮流取,每次可以从任意一堆石子中取走至少一个石子,问先后手谁胜。
解决方法
方法很简单,直接求所有(x_i)的异或和,如果异或和为(0)则先手必败,否则先手必胜。形式化的表达即当且仅当(x_1oplus x_2oplus x_3oplus...oplus x_n=0)时,先手必败。
同理,也就是所以异或和为(0)的状态是(P)状态,所有异或和非(0)的是(N)状态。
证明(伪证):
首先当没有石子的时候,先手必败,此时所有石子的异或和为(0),这个是(P)状态。
接下来我们证明任意一个(N)状态至少能够达到一个(P)状态。
假设当前所有石子个数的异或和为(k),即(oplus_{i=1}^nx_i=k),那么,必定存在一个(x_i)满足(x_i)二进制位上存在(k)的最高位,并且不难证明(x_ioplus k<x_i),那么,将(x_i)异或上(k)之后,剩下所有的数的异或和恰好为(0),又回到了一个(P)状态。
而一个(P)状态的异或和为(0),任何一个数减小之后异或和一定不为(0),所以可以证明任何一个(P)状态的后继状态都是(N)状态。
综上,异或和为(0)的状态先手必败,其他情况先手必胜。
拓展形式
-
每次取的石子数存在上界(m)
这个是(Bash Game+Nim Game),只需要把所有石子按照(m+1)取模再考虑(Nim)游戏就好了。
-
每次允许从(k)堆石子中取((Nim_k))
我们一般考虑的情况是(Nim_1),我们的解法是考虑(2)进制下的异或和是否为(0),而异或和是不进位的加法,同理,对于(Nim_k)的情况,我们考虑(k+1)进制下每一位不进位加法的结果,如果每一位都是(0)的话就是(P)局面,否则是(N)局面。
-
阶梯博弈:博弈在阶梯上进行,每次可以将一堆的若干式子移动到上一阶去,不可操作者输。
忽略所有的偶数阶梯,只留下奇数阶梯,转化为普通的(Nim)游戏。大致的思路是这样的:首先终止状态一定是所有石子都在(0)号阶梯,即一个偶数阶梯。那么如果对方移动了一个偶数阶梯上的石子,那么你可以在移动结束的那个奇数阶梯,直接把等数量的石子继续向前移动,这样子可以保证偶数阶梯上的石子对于结果没有任何影响。那么如果移动的是一个奇数阶梯,因为偶数阶梯是没有影响的,所以你可以认为移动奇数阶梯就是直接被移走了,那么这就是一个普通的(Nim)游戏了。
题目&模板
(SG)定理和(SG)函数
- (Sprague-Grundy)定理:所有一般胜利下的无偏博弈(定义在上面)都能够转化成尼姆数表达的尼姆堆博弈,一个无偏博弈的尼姆值定义为这个博弈的等价尼姆数。(抄自(YMD)课件)
- (SG)函数:对于每一个状态的一个尼姆数的函数又被称作(Sprague-Grundy)函数。
翻译成人话就是:对于当前游戏(X),它可以拆分成若干个子游戏(x_1,x_2,x_3,...,x_n)。那么(SG(X)=SG(x_1)oplus SG(x_2)oplus...oplus SG(x_n))。
接下来定义(mex)运算,(mex)运算是对于一个集合(S)而言的,(mex(S))表示的是最小的、不属于集合(S)的非负整数。例如(mex{1,2,3}=0,mex{phi}=0)。那么我们有运算(SG(x)=mex{SG(y),<x,y>in E}),其中(E)是边集。即对于当前状态(x)的(SG)函数,它的值定义为所有的后继状态的(mex)值。对于(SG)函数为(0)的位置一定是(P)位置,(SG)函数非(0)的位置是(N)位置。
这里直接空说很不好,我们举个例子。
HDU1848 Fibonacci again and again,为了节约篇幅,直接戳链接看题目&题解&代码。
事实上,注意"后继"这个词语,我们不难发现上述的东西可以理解为一个(DAG)上的问题。
(Anti-SG)游戏&(SJ)定理
基本问题
决策集合为空者的操作者胜利。翻译成(Nim)一点的问题就是,给定(n)堆式子,每次每个人可以从任意一堆石子中拿走不少于一个的石子,拿走最后一个石子的人输。
解决方法
(SJ)定理:对于一个(Anti-SG)游戏,如果我们规定当前局面中所有单一游戏的(SG)为(0)时,游戏结束,则先手必胜的条件为:
- 游戏的(SG)值不为(0),且存在一个单一游戏的(SG)值大于(1)
- 游戏的(SG)值为(0),且不存在一个单一游戏的(SG)值大于(1)
题目&模板
(Multi-SG)游戏
基本模型
决策集合为空的操作者输。一个单一游戏的后继可以是多个单一游戏。还是写成(Nim)一点的式子,给定你(n)堆石子,每次可以取走任意数量个,或者将一堆式子拆分成两堆(事实上更多也是可行的)非空石子,不能操作者输,判定胜负。
解决方法
还是可以使用(SG)函数解决,举个例子,比如当前存在一堆(3)个石子,那么可以直接走(0,1,2,3)个石子,也可以拆分成((1,2))两堆,因此(SG(3)=mex{SG(0),SG(1),SG(2),SG(3),SG((1,2))=SG(1)oplus SG(2)})。
那么这个问题本质上还是一个(Nim)游戏,可以直接用(SG)函数解决。
同时,对于这样每次可以拆分两堆的(Multi-SG)游戏,打表后发现有这样一个性质:
题目&模板
(Every-SG)游戏
基本模型
对于没有结束的任何一个单一游戏,操作者必须对其进行一步操作,无法操作者输。
解决方法
所有游戏都是独立的,并且我们发现无法操作者输,而同时又在进行多个游戏。因此,我们知道胜负情况只与最后结束的游戏的胜负情况相关。既然只与最后结束的游戏相关,那么我们这样分析:首先对于一个能够取得胜利的游戏,我们必定会取得胜利,这样一定不会让结果更差,因为只要赢了,这局游戏就一定不会让自己输。那么对于所有单个游戏的胜负情况,我们一定可以判定,但是对于整个(Every-SG)的情况,我们只能够通过最后结束的游戏判定。所以,对于一个我们必胜的游戏,我们一定会想办法将其尽可能的向后拖,即我们期望它尽可能完的结束;反过来,对于一个必败的游戏,我们一定会让他尽可能早的结束。这几句推论正确的理由都是所有游戏都是互相独立的。
那么,我们首先可以判定出所有位置是(N)点还是(P)点,然后根据必胜和必败的关系,我们必定要决策步数最小还是步数最大,那么这个就非常类似于一个(min-max)搜索。至于(N)点和(P)点的判定我们可以很容易的用(SG)函数表示出来。我们定义(step(x))为状态(x)时(在满足(N/P)的条件下)的步数,我们可以得到这样一个转移:
不难发现对于一个(P)状态,(step)一定是偶数,对于一个(N)状态,(step)一定是一个奇数。那么对于这样一个游戏,先手必胜的条件就变成了当且仅当所有单一游戏的最大(step)是一个奇数。
题目&模板
翻硬币游戏
题目
有(n)枚硬币排成一排,依次编号(1)到(N),有的正面朝上,有的反面朝上。现在按照一定的规则翻硬币(比如每次只能翻一枚或者两枚,或者每次只能翻动连续的几枚),但是强制要求最靠右的硬币必须从正面被翻到了反面。操作集合为空者负。
解决方法
结论是这样的:当前局面的(SG)值是所有正面朝上的硬币单独存在时的(SG)值的异或和。
证明?我也不会啊。可以感性理解一下,无论如何最右边的硬币都要翻,它翻了之后必定改变前面的状态,但是前面的状态是什么似乎和之前的状态无关(假装能够说服我自己),之和之前的状态和现在状态的差别(也就是看成(01)串后的异或和)相关,所以你可以把游戏拆分成所有正面朝上的硬币的子游戏。
链接中给出这么多游戏的主要目的是因为直接使用(SG)函数求解效率太低,很多时候利用(SG)函数打表找规律才是最好的方法。
树的删边游戏
题目
给定一个(n)个节点的有根树,两人轮流删边,删去边之后,不和根节点联通的部分都会被移除。不能操作者输,判断胜负。
解决方法
结论:定义叶子节点的(SG)值为(0),其他所有节点的(SG)值为它所有儿子的(SG)值加(1)后的异或和。
结尾
对于这一部分的博弈,这些东西都是比较常见的博弈模型。它们主要利用(SG)函数求解,换而言之,(SG)函数就是这篇文章中所有博弈游戏的灵魂。所有的一切都是利用(SG)函数区分(N/P)状态,利用(SG)函数,也可以得到很多题目不会差于对抗搜索复杂度的算法。
但是有很多的博弈题目似乎并用不上(SG)函数,或者说很难用上,这个时候的解决方法一般就是要么直接打表找规律,要么通过分析和构造,找到先手必胜的条件再来进行判断。这些非常见的博弈模型也就不是我在这里能够穷举完的啦。