【问题标题】:Where is my flaw in solving the Misere Nim game我在解决 Misere Nim 游戏中的缺陷在哪里
【发布时间】:2017-05-16 06:58:39
【问题描述】:

游戏是你有N一堆石头,每个玩家轮到他必须从一堆石头中移走至少1块石头,移走最后一块石头的玩家输了。

从基本案例开始,我在十几个案例中写出了获胜者

/*
    stones             | winner  | N | ones 
    ========================================
    {1}                | Second  | 1 |  1   
    {i}, i>1           | First   | 1 |  0
    {1,1}              | First   | 2 |  2
    {1,i}, i>1         | First   | 2 |  1
    {i,j}, i,j>1       | Second  | 2 |  0
    {1,1,1}            | Second  | 3 |  3
    {1,1,i}, i>1       | First   | 3 |  2
    {1,i,j}, i,j>1     | First   | 3 |  1
    {i,j,k}, i,j,k>1   | First   | 3 |  0
    {1,1,1,1}          | First   | 4 |  4
    {1,1,1,i}          | First   | 4 |  3
    {1,1,i,j}, i,j>1   | Second  | 4 |  2
    {1,i,j,k}, i,j,k>1 | First   | 4 |  1
    {i,j,k,m}, ...     | Second  | 4 |  0
*/

我想我从中推导出了一个公式

static string GetWinner(int[] piles)
{
    int n = piles.Length, m = piles.Count(stones => stones == 1);
    if(m == n) // one stone per pile
        return n % 2 == 0 ? "First" : "Second";
    // if here, m < n
    return n % 2 == 0 ? (m % 2 == 0 ? "Second" : "First") : "First";
}

但这导致测试用例 {2,1,3} 失败,这应该导致 "Second"

我尝试使用以下事实。

  • 如果是2,一堆大于2 的任何数量的石头都会给出相同的结果。原因是如果它大于2 并且玩家没有在那个转牌圈将牌堆缩小到1 那么玩家基本上已经让他的对手转牌了。

但是,我可能有些不对劲..

【问题讨论】:

  • 我不明白你为什么要测试N,据我所知游戏只与M有关,无论如何你可能想让你的问题更清楚
  • 有多少玩家?如果游戏目标是宣布 1 个较松,这意味着应该有超过 1 个赢家。那么,当您需要找到较松的人时,为什么要找到赢家

标签: c# algorithm game-theory


【解决方案1】:

我认为您的以下陈述是错误的:

一堆大于 2 的石头如果是 2 会给出相同的结果

如果状态是 {1,2,2},第一个玩家可以通过移除 1 个棋子获胜。如果状态为 {1,2,3},则第一个玩家无法获胜。所以石头的数量是2还是3是有区别的。

因为如果它大于 2 并且玩家在该回合没有将牌堆缩小到 1,那么玩家基本上已经给了他的对手。

这是正确的,只是有时“希望”将回合让给其他玩家,即超越回合。

最佳策略与二进制表示中每堆中的项目数的异或有关。有关最佳解决方案和详细信息,请参阅https://en.wikipedia.org/wiki/Nim

【讨论】:

    【解决方案2】:

    我无法深入理解答案背后的数学,但经过一些研究和优化,这是我为python3提出的解决方案:

    
    from functools import reduce
    
    def misereNim(s):
        if(max(s)==1):
            return "First" if (len(s) % 2 ==0) else "Second"
        else:
            xor = reduce((lambda x, y: x ^ y), s)
            return "Second" if xor == 0 else "First"
    
    if __name__ == '__main__':
    
        s = [9, 8, 4, 4, 4, 7]
    
        result = misereNim(s)
        print(result)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-12-07
      • 1970-01-01
      • 1970-01-01
      • 2015-09-25
      • 2016-10-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多