📅  最后修改于: 2023-12-03 15:11:37.903000             🧑  作者: Mango
Sprague-Grundy 定理是组合博弈论中的一个重要定理,可以用于求解一类特殊的博弈问题。在这篇文章中,我们会介绍 Sprague-Grundy 定理的定义、推导过程、以及如何使用它解决博弈问题。
Sprague-Grundy 定理可用于求解任意两人、零和、完全信息、有限回合的游戏的必胜策略。这里有两种等价的定义方式:
根据这两个定义,我们可以得到任意状态的 SG 值。
我们来看一个具体的例子,有一个博弈问题:一堆石子,两人轮流取走若干个石子,不能不取,最后一颗石子的人获胜。这是一个经典的博弈问题,我们可以用 Sprague-Grundy 定理来解决。
首先,我们把这个问题看成是一个状态为石子数的游戏。对于任意一个石子数 $n$,它的后继状态就是 $n-1,n-2,\ldots,n-k$,其中 $k$ 是最多可以取多少个石子。因为我们每次取走的石子数不能超过 $k$,所以 $k$ 是一个定值。
接下来,我们来考虑状态 $n$ 的 SG 值。根据第一种定义,状态 $n$ 的 SG 值等于所有后继状态的 SG 值的 $\text{xor}$ 和加一。也就是说:
$$ \mathrm{SG}(n) = \mathrm{mex} { \mathrm{SG}(n-1),\ \mathrm{SG}(n-2),\ \ldots,\ \mathrm{SG}(n-k) } $$
其中 $\mathrm{mex}$ 表示取集合中最小的不在集合中出现的自然数。我们可以用 $f(x)$ 表示 $\mathrm{SG}(x)$:
$$ f(x) = \mathrm{mex} { f(x-1),\ f(x-2),\ \ldots,\ f(x-k) } $$
对于 $k=1$ 的情况,这里的 $\mathrm{mex}$ 可以简单的用异或替换,即:
$$ f(x) = \mathrm{mex} { f(x-1) \oplus 1 } $$
整个推导过程的前提是我们要知道 $\mathrm{SG}(0)=0$。这个比较容易理解,因为当石子数为 $0$ 时,游戏必须停止,此时 SG 值为 $0$。
最后我们来看如何利用 SG 值求解博弈问题。如果两个人分别采用最优策略,那么如果某个位置的 SG 值为 $0$,那么该人必胜;反之,如果 SG 值不为 $0$,那么该人必败。因此,我们可以用 DP 求出所有状态的 SG 值,然后通过 SG 值来求解必胜策略。
def sg(n: int, k: int) -> int:
"""
计算石子游戏中 SG 值
:param n: 石子数
:param k: 每次可以取的石子数的最大值
:return: SG 值
"""
f = [-1] * (n + 1)
f[0] = 0
for i in range(1, n + 1):
s = set()
for j in range(1, min(i, k) + 1):
s.add(f[i-j] ^ 1)
f[i] = mex(s)
return f[n]
def mex(s: set) -> int:
"""
求集合 s 中最小的不在其中的自然数
:param s: 集合
:return: 最小的不在其中的自然数
"""
i = 0
while i in s:
i += 1
return i