【问题标题】:Most effecient way to compute a series of moves in peg solitaire在 peg solitaire 中计算一系列移动的最有效方法
【发布时间】:2010-09-01 14:06:00
【问题描述】:

给定一个任意的钉子接龙棋盘配置,计算导致“游戏结束”位置的任何一系列移动的最有效方法是什么。

例如,标准起始位置是:

..***..
..***..
*******
***O***
*******
..***..
..***..

而“结束游戏”的位置是:

..OOO..
..OOO..
OOOOOOO
OOO*OOO
OOOOOOO
..OOO..
..OOO..

此处更详细地描述了 Peg solitare:Wikipedia,我们正在考虑“英文板”变体。

我很确定,在一台合理的计算机上,比如 P4 3Ghz,只需几秒钟就可以解决任何给定的起始板。

目前这是我最好的策略:

def solve:
    for every possible move:
        make the move.
        if we haven't seen a rotation or flip of this board before:
            solve()
            if solved: return
        undo the move.

【问题讨论】:

  • 这是作业,还是面试题?
  • @Nathon 我在中学,这既不是作业也不是面试问题。只是我挖出来的东西,我觉得很奇怪。

标签: language-agnostic dynamic-programming game-theory


【解决方案1】:

您链接到的维基百科文章已经提到只有 3,626,632 个可能的棋盘位置,因此任何现代计算机都可以轻松地对空间进行详尽的搜索。

你上面的算法是对的,诀窍是实现“以前没有见过这个板的旋转或翻转”,你可以使用哈希表来做到这一点。您可能不需要“撤消移动”行,因为真正的实现会将棋盘状态作为参数传递给递归调用,因此您可以使用堆栈来存储状态。

另外,不清楚您所说的“高效”是什么意思。

如果您想找到通向获胜阶段的所有动作序列,那么您需要进行详尽的搜索。

如果你想找到最短的序列,那么你可以使用分支定界算法在早期切断一些搜索树。如果您能想出一个好的静态启发式算法,那么您可以尝试 A* 或其变体之一。

【讨论】:

  • 我只想找到1条路径,可以是任意长度。此外,在 Peg Solitaire 中,所有解决方案的长度几乎都相同。目前我正在使用具有唯一板标识符的 python 列表来检查板是否已被看到。由于我使用的是 Python,通过引用传递,我认为我需要撤消移动,特别是因为我通过 Board 类设计的创建效率很低,但更改速度非常快。
  • 哦,好吧,如果所有解决方案的长度都相同(我现在明白为什么,每一步都会带走一个钉子)然后分支和绑定就不行了,除非你找到一些启发式方法,说“从这个声明不可能达成解决方案”。我认为应该存在,对吧?我想不出一个……
  • 我在一些论文中发现了所谓的Pagoda function。它应该告诉一个棋盘状态是否可以获胜,但我真的不明白如何应用它。
【解决方案2】:

从完成状态开始,及时倒退。每一步都是一跳,在棋盘上留下一个额外的钉子。

在每个时间点,您都可以进行多个不移动,因此您将生成移动树。遍历该树(深度优先或广度),当它达到起始状态或不再有任何可能的移动时停止任何分支。输出导致原始起始状态的路径列表。

【讨论】:

  • 这与原始问题完全相反,AFAIK 它并没有降低其复杂性。
猜你喜欢
  • 2011-10-10
  • 1970-01-01
  • 1970-01-01
  • 2013-03-29
  • 1970-01-01
  • 2012-08-12
  • 1970-01-01
  • 2013-04-19
  • 2012-07-01
相关资源
最近更新 更多