博弈论,即公平组合游戏,满足下列一些特征:
- 一场游戏有两个玩家,两个玩家轮流行动,是经典的回合制游戏。
- 两个玩家的移动按照规则移动,并且两玩家之间的移动不区分身份。
- 两个玩家按照最优的决策行动,即给定一个局势,能够一开始就区分出先手必胜还是先手必败。
巴什博弈
Brave Game HDU - 1846
现在定义两个字母: N N N 为先手必胜, P P P 为先手必败。
在该例题中,每次可以取1~m个石子,现在先假设能够取 m = 3 m=3 m=3 颗石子,画出的 N − P N-P N−P 关系图如下:
石子 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
---|---|---|---|---|---|---|---|---|---|---|---|
状态 | P P P | N N N | N N N | N N N | P P P | N N N | N N N | N N N | P P P | N N N | N N N |
现在解释一下上图:
- 首先对于石子数为 0 0 0 的时候,该状态无路可走,所以先手必败, P P P 点。
- 对于石子数为
1
1
1~
3
3
3 的时候,因为他们都能够通往状态为
0
0
0 的点,所以能够在先手取完后,让后手得到状态
P
P
P ,既然对手必败了,所以对于自身无疑必胜。
- 现对于上一点详细介绍:对于一个状态,若其通往的下一个子状态包含 P P P 状态,则本状态必定先手必胜,即 N N N 点。例如上面图示,当石子数为 3 3 3 的时候,可以取一个通往 2 2 2 号点,可以取两个通往 1 1 1 号点,可以取三个通往 0 0 0 号点,其中 0 0 0 号点是 P P P 状态,所以 3 3 3 号点先手必胜。
- 对于石子数是
4
4
4 的时候,他可以取一个通往
3
3
3 号点,取两个通往
2
2
2 号点,取三个通往
1
1
1 号点;其中这三个子状态都是
N
N
N 状态,所以
4
4
4 号点先手必败,即
P
P
P 点。
- 现对于上一点详细介绍:对于一个状态,若其通往的下一个状态全部都是 N N N 状态,即无论自己怎么决策行动,都能让对手获胜,所以该状态必定先手必败,即 P P P 点。
- 后面 5 5 5~ 10 10 10 可以根据同样的方法推得,简单明了的说,NP关系推理几乎就是图游戏:通往的下一个状态,即子结点,包含 P P P 状态,则该状态是 N N N 点;若子结点无 P P P 状态,则该状态为 N N N 点。
- NP关系推理的题目基本上都是通过找规律来解题。在本题中, 显然当 n % ( m + 1 ) = = 0 n\%(m+1)==0 n%(m+1)==0 的时候是 P P P 点,其余情况则是 N N N 点。
尼姆博弈
现通过一道例题引入 S G SG SG 函数:
-
定义一个数 x x x 的 S G SG SG 值: s g ( x ) = sg(x)= sg(x)= { v ∣ m e x [ s g ( v ) ] {v|mex[sg(v)]} v∣mex[sg(v)]} ,其中 v v v 是 x x x 可以通往的下个状态点
-
假设在一局取石子游戏中,能够取 1 , 2 , 4 1,2,4 1,2,4 个石子,并且假设 0 0 0 号点的 S G SG SG 值为0
-
画出的 s g sg sg 表如下:
石子 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
---|---|---|---|---|---|---|---|---|---|---|---|
S G SG SG 值 | 0 | 1 | 2 | 0 | 1 | 2 | 0 | 1 | 2 | 0 | 1 |
-
对于 4 4 4 号点,取一个通往 3 3 3 号点: s g ( 3 ) = 0 sg(3)=0 sg(3)=0 ;取两个通往 2 2 2 号点: s g ( 2 ) = 2 sg(2)=2 sg(2)=2 ;取四个通往 0 0 0 号点: s g ( 0 ) = 0 sg(0)=0 sg(0)=0 。所以取 m e x [ 0 , 2 ] = 1 mex[0,2]=1 mex[0,2]=1, 所以 s g ( 4 ) = 1 sg(4)=1 sg(4)=1
-
其余点同理,取 m e x mex mex 即可。
-
由上图可知, S G SG SG 函数也是有规律可寻。
-
对于能取 1 , 2 , 4 1,2,4 1,2,4 个石子的 s g sg sg 函数代码如下:
const int N=1e3+10; int sg[N]; bool vis[N]; void getSG() { sg[0] = 0; for (int i = 1; i <= 1000; ++i) { memset(vis, false, sizeof vis); //记录通往下一个状态的sg值 if (i - 1 >= 0) vis[sg[i - 1]] = true; if (i - 2 >= 0) vis[sg[i - 2]] = true; if (i - 4 >= 0) vis[sg[i - 4]] = true; //取mex for (int j = 0;; ++j) { if (!vis[j]) { sg[i] = j; break; } } } }
Being a Good Boy in Spring Festival HDU - 1850
现假设有 n n n 堆牌,对于一个堆 i i i ,假设该堆的 S G SG SG 值为 s g ( a i ) sg(a_i) sg(ai) ,那么游戏的总状态 S G SG SG = s g ( a 1 ) ⊕ s g ( a 2 ) ⊕ s g ( a 3 ) ⊕ . . . ⊕ s g ( a n ) sg(a_1)\oplus sg(a_2)\oplus sg(a_3)\oplus ... \oplus sg(a_n) sg(a1)⊕sg(a2)⊕sg(a3)⊕...⊕sg(an)
定理:
-
如果 S G ≠ 0 SG≠0 SG=0 ,则该游戏先手必胜,为 N N N 点。
-
反之如果 S G = 0 SG=0 SG=0 ,则该游戏先手必败,为 P P P 点。
因为本题中,对于一个堆中有 x x x 个数,每次可以从堆中取 [ 1 1 1, x x x] 个数, 所以 s g ( x ) = x sg(x)=x sg(x)=x 。
关于本题后面输出解的问题,请查看该博客
阶梯博弈
这篇博客讲得不错:传送门
关于阶梯博弈,并没有找到基本的板子题,有个稍微类似的二维题目:Crazy Calendar LightOJ - 1393
变形题:Georgia and Bob POJ - 1704;Climbing the Hill HDU - 4315
关于斐波那契博弈以及 k k k 倍动态减法的详解,请查阅国家集训队论文
例题:A simple stone game HDU - 2486
参考书目
[1]罗勇军,郭卫斌.算法竞赛入门到进阶.