博弈论的题目有如下特点:
- 有两名选手
- 两名选手交替操作,每次一步,每步都在有限的合法集合中选取一种进行
- 在任何情况下,合法操作只取决于情况本身,与选手无关
- 游戏败北的条件为:当某位选手需要进行操作时,当前没有任何可以执行的合法操作
下面介绍几个经典的博弈。
巴什博弈(Bash Game)
一堆n个物品,两个人轮流从中取出1~m个,最后取光者胜(不能继续取的人输)。
同余定理:$n=k*(m+1)+r$,先者拿走$r$个,那么后者无论拿走$1~m$个先者只要的数目使和为$m+1$,那么先手必赢。反之若$n=k*(m+1)$,那么先手无论怎样都会输。
if (n % (m + 1)) return false; else return true;
威佐夫博弈(Wythoff Game)
有两堆各若干物品,两个人轮流从任意一堆中至少取出一个或者从两堆中取出同样多的物品,规定每次至少取一个,至多不限,最后取光者胜。
这里的必输局势:(0,0)、(1,2)、(3,5)、(4,7)、(6,10)、(8,13)、(9,15)、(11,18)、(12,20)。从这些必输局势可以发现,每组的第一个是前面没有出现的最小正整数,$a_k = [k * (1+\sqrt{5}) / 2],\ b_k = a_k + k,\ k = 0,1,2,3...$。
所以,先求出差值,差值*黄金分割比 == 最小值的话后手赢,否者先手赢。
double r = (sqrt(5) + 1) / 2; int d = abs(a - b) * r; if (d != min(a, b)) return true; else false;
注:如果a,b的值非常大的话,需要高精度来计算这个double类型的r。
尼姆博弈(Nimm Game)
有n堆物品,两人轮流取,每次取某堆中不少于1个,最后取完者胜。
假如有3堆物品(a,b,c)
(0,0,0)状态时先手是一个必输局势因为没有东西可取,(0,n,n) 状态时也是必输局势只要后者在另一堆取得物品与前者一样多时那么前者也就是必输局势。慢分析(1,2,3)也是一个必输局势。如果我们将其转化为二进制形式并通过异或运算(^)我们会发现:
0001^0010^0011=0000
通过验证所有的堆数量累^后只要为0就都是必输局势,所以我们就只要记住这个规则:将n堆物品数量全部异或后结果为0者必败,否则必胜。
int res = 0; for (int i = 1; i <= n; i++) res ^= arr[i]; if (res) return true; else return false;
但是,实际问题中不可能给出如此标准的博弈模型,对于更加一般的博弈问题,我们该如何求解呢?通过SG函数转换为尼姆博弈。
SG函数
首先给出一种ICG博弈游戏模型,给定一个有向无环图和一个起始顶点上的一枚棋子,两名选手交替的将这枚棋子沿着有向边进行移动,无法移动者判负。
将ICG问题进行转化:任何一个ICG都可以通过把每个局面看作一个顶点,对每个局面和它的子局面连一条有向边来抽象这个“有向图游戏”。
于是我们将ICG问题转化为上述这个游戏,再通过寻找这个游戏的一般解法来处理ICG问题。
首先定义mex(minimal excludant)运算,这是定义于一个集合的运算,表示最小的不属于这个集合的最小非负整数。例如mex{0,1,2,4}=3,mex{2,3,4}=0,mex{}=0.
SG函数(Sprague-Grundy):对于一个给定的有向无环图,定义关于这个图的每个顶点的SG函数如下:$sg(x) = mex\{sg(y) \ | \ y是x的后继 \}$