【问题标题】:Explanation on Stone Nim GameStone Nim游戏说明
【发布时间】:2019-06-26 17:26:35
【问题描述】:

我正在做一个编码问题,我以某种方式通过了所有测试用例,但我不明白到底发生了什么。问题是经典 nim 游戏的一个小转折:

有两个玩家A和B。有N堆各种石头。如果堆小于K,每个玩家可以拿任意数量的石头,否则他们必须拿K的倍数。最后拿石头的人获胜。

蟒蛇

# solution -> will A win the game of piles, k?
def solution(piles, k):
    gn = 0 # Grundy number
    for pile in piles:
        if pile % 2 != 0:
            gn ^= pile + 1
        else:
            gn ^= pile - 1
    return gn != 0

我不确定是否有足够的测试用例,但这里甚至没有使用k。老实说,我什至很难理解gn(Grundy 号码)的真正含义。我意识到如果所有堆的异或不为零,则可以证明赢得 Nim 游戏,但我真的不明白为什么这种变化需要检查堆的奇偶性。

【问题讨论】:

  • 如果您在浏览器中搜索“Nim Grundy number”,您会找到比我们在此处管理的更能解释这一点的参考资料。
  • @Prune 当然可以。我仍然想了解为什么k 不会影响解决方案。
  • 我主要编辑了这个问题,所以我可以删除我的反对票。我的直觉是,由于您引用的原因,给定的解决方案是不够的。当所有堆的石头少于k 时,游戏会减少到常规 Nim,但之前的情况应该考虑k。我将不得不咨询我的 Grundy-Conway 负责人...

标签: python bit-manipulation combinatorics game-theory


【解决方案1】:

首先,给定的解决方案不正确。你注意到它没有使用k,这确实是一个很大的危险信号。您还可以查看它为单桩游戏给出的结果,其中似乎说玩家 A 只有在您应该很快能够显示不正确的桩的大小时才会获胜。

不过,答案的结构是正确的。 Grundy 数的很多功能在于组合游戏状态的 Grundy 数是单个游戏状态的 Grundy 数的 nim 和(在有限序数的情况下 XOR)。 (这仅适用于组合游戏状态的一种非常具体的方式,但事实证明这是将 Nim 堆放在一起的自然方式。)因此,这个问题确实可以通过找到每个堆的 Grundy 数来解决(考虑 @987654322 @) 并对它们进行异或运算以获得完整游戏状态的 Grundy 编号。 (在 Nim 中,您可以从一堆石头中取出任意数量的石头并通过拿走最后一颗石头来获胜,一堆的 Grundy 数只是一堆大小。这就是为什么该版本 Nim 的解决方案只是 XOR-s桩的大小。)

因此,理所当然地,您可以通过为给定k 的单个桩找到正确的 Grundy 值来解决问题。你只需要考虑一堆游戏就可以做到这一点。这实际上是一个非常经典的问题,而且 IMO 比多桩 Nim 更容易正确分析。你应该试一试。

关于如何看待 Grundy 数字,有很多地方可以阅读,但这是我的方法。需要理解的是,为什么两种游戏状态的组合可以让前一个玩家 (B) 在 Grundy 数字相等时准确地获胜。

为此,我们只需要考虑移动对两个状态的 Grundy 数的影响。

根据定义为后继状态的最小排除值,总是有一个移动将状态的 Grundy 数更改为任何较低的值(即 n 可以变成从 0n - 1 的任何数字) .从来没有一个动作可以让 Grundy 数字保持不变。可能有也可能没有增加格伦迪数的动作。

那么,在两个状态组合相同Grundy数的情况下,玩家B可以通过“模仿策略”获胜。如果玩家 A 的动作减少了一个状态的 Grundy 数,玩家 B 可以通过将另一个状态的 Grundy 数减少到相同的值来“复制”。如果玩家 A 的动作增加了一个状态的 Grundy 数,玩家 B 可以通过在相同状态下移动以将其减少到与之前相同的值来“撤消”它。 (我们的游戏是有限的,所以我们不必担心做与不做的无限循环。)这些是 A 唯一能做的事情。 (请记住,重要的是,没有任何动作可以让 Grundy 数字保持不变。)

如果各州没有相同的 Grundy 号码,那么第一个玩家获胜的方式就很清楚了;他们只是减少具有较高值的​​状态的数量以匹配具有较低值的状态。这将事情简化为之前的场景。

在这里我们应该注意,最小排除值定义允许我们根据其后继者递归地构造任何状态的 Grundy 数(至少对于有限博弈而言)。没有选择,所以这些数字实际上是明确定义的。

下一个要解决的问题是为什么我们可以计算组合状态的 Grundy 数。我宁愿在这里根本不考虑 XOR。我们可以纯粹从最小排除值属性定义这个 nim sum 操作。我们抽象地认为nim_sum(x, y)的继任者是{nim_sum(k, y) for k in 0..x-1}{nim_sum(x, k) for k in 0..y-1};换句话说,在一个子状态或另一个子状态上采取行动。 (我们可以忽略增加 Grundy 数的子状态之一的后继者,因为这样的状态将拥有原始状态的所有后继者加上 nim_sum(x, y) 本身作为另一个后继者,因此它必须具有严格更大的 Grundy 数. 是的,这有点令人费解。)这与 XOR 相同。我对此没有特别好的解释,但我觉得这对于基本理解来说并不是必需的。重要的是它是一个定义明确的操作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-29
    • 1970-01-01
    • 2019-09-17
    • 1970-01-01
    相关资源
    最近更新 更多