3x3网格拼图解决(JS)

时间:2012-03-06 15:23:49

标签: algorithm grid

我将图像分成3x3网格。网格由数组表示。每个列或行都可以旋转。例如,顶行[1,2,3]可能会变为[3,1,2]等。

数组最终需要:

[1,2,3]
[4,5,6]
[7,8,9]

将从以下内容开始:

[5,3,9]
[7,1,4]
[8,6,2]

它总是可以解决,所以不需要检查。

我尝试了一种长时间寻找'1'并向左移动然后向上移动到正确位置的方法,依此类推2,3,......但最终会绕圈旋转。

任何帮助都会受到赞赏,即使你能给我一个起点/参考......我似乎无法通过这个来思考。

2 个答案:

答案 0 :(得分:1)

你的问题是,移动一个值的举动会搞砸别人。我怀疑有足够的集理论你可以找出一个精确的解决方案,但这是一个更有机会工作的启发式。

首先请注意,如果一行中的每个数字都属于该行,那么要解决这个问题要么很简单,要么交换某些值。例如,[2,3,1]是微不足道的,而[3,2,1]是交换的。

因此,比放置1左上角更“容易”的目标是让所有行都进入该状态。我们怎么能这样做?让我们看看列......

如果列中包含每行中的一个数字,那么我们处于与上面类似的状态(移位要么很简单,所以数字在正确的行中,或者它被交换)。

所以,我建议的是:

   for column in columns:
       if column is not one value from each row:
          pick a value from column that is from a duplicate row
          rotate that row
   for column in columns:
       as well as possible, shift until each value is in correct row
   for row in rows:
       as well as possible, shift until each value is in correct column

现在,这不能保证工作,虽然它会趋于接近,并且可以解决一些“几乎正确”的安排。

所以我接下来会把它放在一个循环中,并在每次运行时记录一个状态的“哈希”(例如,一个包含逐行读取的值的字符串)。然后在每次调用时,如果我检测到(通过检查散列是否是我们已经看过的那个)状态已经发生(所以我们重复自己),我会调用一个混合的“随机混乱”。

因此我们的想法是,一旦我们接近,我们就有机会有机会工作,而当我们陷入循环时,我们会采取一种随机的方式。

正如我所说,我相信有更明智的方法可以做到这一点,但如果我绝望并且无法在谷歌上找到任何东西,那就是那种启发式我会尝试...我甚至不确定以上是对的,但更普遍的策略是:

  • 找出可以解决非常接近的解决方案的东西(从某种意义上说,找出拼图是“线性的”)
  • 尝试重复
  • 如果重复则洗牌

这就是我在这里说的全部。

答案 1 :(得分:1)

由于网格是3x3,您不仅可以找到解决方案,还可以找到最小次移动来解决问题。

为此,您需要使用Breadth First Search

将每个配置表示为9个元素的线性数组。每次移动后,您将达到不同的配置。由于数组基本上是1-9之间数字的排列,所以只有9个! = 362,880种不同的配置。

如果我们将每个配置视为一个节点,并且将每个移动视为边缘,我们可以在O(n)中探索整个图,其中n是配置的数量。我们需要确保,我们不会重新解决之前已经看到过的配置,因此您需要一个访问数组,该数组会在看到它时标记所访问的每个配置。

当您达到“已解决”配置时,您可以追溯使用“父”数组所采取的移动,该数组存储您来自的配置。

还要注意,如果它是一个4x4网格,问题就会非常棘手,因为n等于(4x4)! = 16! = 2.09227899×10 ^ 13。但对于像这样的小问题,你可以很快找到解决方案。

编辑:

TL; DR

  • 保证工作,并且相当快。 362,880对于今天的电脑而言是一个非常小的数字
  • 它会找到最短的动作序列。