📜  组合博弈论 |设置 3(Grundy NumbersNimbers 和 Mex)(1)

📅  最后修改于: 2023-12-03 14:56:50.726000             🧑  作者: Mango

组合博弈论 | 设置 3(Grundy Numbers/Nimbers 和 Mex)

组合游戏是一类描述两个人交替行动,根据某些规则进行决策的游戏。Grundy Numbers和Mex是组合游戏中比较常用的概念,用于求解游戏的必胜策略。

Grundy Numbers / Nimbers

Grundy Number又叫Nimbers,是组合游戏中的一个概念,用于描述当前状态的价值。对于每个状态,都有一个唯一的Grundy Number,用于表示它的价值。

Grundy Number的求解方法如下:

  1. 对于一个游戏状态,我们将它的所有子状态的Grundy Number求XOR(异或)起来,得到组合游戏的SG函数值。
  2. 对于当前状态的Grundy Number,它等于先手可以达到的最小非负整数。
# 计算Grundy Number
def calc_grundy(n):
    s = set()
    for i in range(1, n//2+1):
        s.add(calc_grundy(i) ^ calc_grundy(n-i))
    res = 0
    while res in s:
        res += 1
    return res
Mex

Mex是组合游戏中的另一个概念,表示集合中没有出现过的最小自然数,即最小的不属于集合的非负整数。Mex函数通常用于计算Grundy Number。

# 计算Mex
def mex(s):
    res = 0
    while res in s:
        res += 1
    return res
组合博弈示例

取石子游戏是组合游戏的经典例子,我们可以用Grundy Number求解。假设有n堆石子,每次可以取任意堆石子的任意数量,先取完石子的玩家获胜。

对于当前状态,我们将每堆石子的数量视为一个元素,将所有元素的Grundy Number进行异或,得到SG函数值。我们可以发现,SG函数值等于所有堆石子数量的异或和。因此,我们只需要判断这个异或和是否为0即可求出必胜策略。

# 计算取石子游戏的必胜策略
def stone_game(n, stones):
    s = 0
    for x in stones:
        s ^= x
    return s != 0
总结

Grundy Number和Mex是组合游戏中比较常用的概念,用于求解游戏的必胜策略。计算Grundy Number的方法是将当前状态的所有子状态的Grundy Number异或起来,然后求得Mex。对于当前状态的Grundy Number,它等于先手可以达到的最小非负整数。Mex函数用于计算Grundy Number,并且也可用于计算其他组合游戏中的价值。