【问题标题】:Minimum steps to reach the end of game达到游戏结束的最小步骤
【发布时间】:2014-05-17 00:46:47
【问题描述】:

我正在编写一个非常简单的游戏。

  • 给定 n 块有 k 种颜色的积木放在一个圆圈中
  • 如果砖块被移除,与之相邻且颜色相同的砖块将被移除。
  • 每走一步,玩家只能移走一块砖(但如果旁边有一块颜色相同的砖,则不计步)
  • 如果所有积木都被移走,游戏结束

如何获得到达游戏结束所需的最少步数? (我目前的解决方案是回溯,正在考虑动态规划)

示例:

4 bricks with 3 colors R, G, B place like this:
R G B B G R B G B R R G (R) (let number it 0, 1, 2, ...)

Remove 2 -> 3 will be removed (step = 0)
R G <B> <B> G R B G B R R G

Remove 0 (step = 1)
<R> G * * G R B G B R R G

Remove 4 -> 1, 11 will be removed (step = 1)
* <G> * * <G> R B G B R R <G>

Remove 10 -> 9, 5 will be removed (step = 1)
* * * * * <R> B G B <R> <R> *

Remove 7 (step = 2)
* * * * * * B <G> B * * *

Remove 8 -> 6 removed -> end game, step = 2, minimal
* * * * * * <B> * <B> * * *

真的对不起我的英语

【问题讨论】:

  • "如果一块砖被移除,与之相邻且颜色相同的砖" -- 被移除的砖可能与0、1或2块砖相邻,对吗?
  • 举个例子,让我们以最少的步数运行一款游戏。
  • @Dialectus 请稍等
  • @Dialectus:你有一块砖。最少移动次数:1
  • 哦,好的,谢谢。我添加了中间状态,以便更好地理解。

标签: algorithm dynamic-programming mathematical-optimization


【解决方案1】:

O(N3) 复杂度的解决方案在哪里。

动态规划。要了解它是如何工作的,并且确实如此,请考虑一些删除所有块的序列。现在让我们标记所有后续块,一步一步删除。我们将在初始圆圈上标记它们。每个步骤都可以标记为一段相同颜色的块(之前删除了所有不同的块)。下面是您的示例的此类图片:

initial: RGBBGRBGBRRG
step 1:    BB
step 2:  R
step 3:  -G--G      G
step 4:  -----R   RR-
step 5:  ------B B---
step 6:         G

每个“段”要么不相交,要么前面的段完全在后面的段中。因此,有一种方法可以在某个时候打破循环。在您的示例中,它可以在第 5 和 6 块(或 6 和 7 块)之间完成。

现在您可以看到解决方案的结构 - 我们必须知道完全删除一些连续块的最小步骤数,而不是块的圆圈。为此,我们将有一个动态编程F(i,j)="从 i 到 j 完全删除块所需的最小步骤数"。请注意,可能有j &lt; i,这意味着该段越过初始块中的边缘(如上图中的步骤5)。如果我们可以计算出F,那么答案将是所有F(i, (i+n-1)%n) for i=0..n-1中的最小值。

基础很明显,空段(j == i-1)需要0步,一个块段(i==j)需要1步。

剩下的就更难了。考虑段中的第一个块。 它是在某个步骤中删除的某些块段的开始。它必须在相同颜色的块的某处结束。因此,我们有:

F(i,j) = min{G(i,t)+F(t+1,j) },  i<=t <= j, blocks t and i have the same color

这里,G(i,j) 是另一个动态规划,给出了“从 i 到 j 删除所有块需要多少步,在最后一步同时删除块 i 和 j”的答案。请记住,这里的方块是成直线的,而不是圆的。

我们尝试将t 作为段的结尾,因此我们需要G(i,t) 步骤来删除所有这些块。我们需要另一个F(t+1,j) 步骤来删除所有其他块。

GF 具有相同的基数。现在回头看看上面的图片。片段中的最后一步可能不仅包含两个块 i 和 j(如步骤 3)。它可能有一些中间块。我们将尝试所有可能的中间块:

G(i,j) = min{F(i+1, t-1)+G(t, j)}, i < t <= j, blocks t and i have the same color.

这里发生了什么?我们认为块t 是最后一个删除块的行中的下一个。为此,我们首先必须完全删除it 之间的所有块。它需要F(i+1, t-1) 步骤。然后我们将计算从tj 删除所有块需要多少步骤,而最后删除角块。它需要G(t, j) 步骤。现在可以免费删除块i,因为它与块t相邻,可以在最后一步一起删除。请注意,t 可能等于j。因此我们可以只用两个移除的块来覆盖移动。

此解决方案需要 O(N2) 内存和 O(N3) 时间。 实现它的最简单方法是惰性动态编程(使用递归函数并记住答案)。

如果您还需要步骤顺序,那就有点困难了。每个函数 F 和 G 还应该存储中间变量t 值,它给出了最小答案。然后,您可以使用另一个递归函数重构这些步骤,该函数将仅使用存储的“t”值来镜像 F 和 G 计算。这样你将得到所有的段,现在你可以从最小到最大输出它们。

编辑:

注意,因为jFG 中可以小于i,所以你应该小心。不是i &lt;= t &lt;= j 而是ti 开始并增加直到达到j (它可能会越过终点并从n-1 变为0)。 i &lt; t &lt;= j 类似。

也没有办法为函数传递一个空段,因此j==i-1 不应该有基数。相反,如果没有要删除的块,则不应调用 FG

【讨论】:

    猜你喜欢
    • 2019-11-29
    • 2021-07-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-07
    • 1970-01-01
    • 1970-01-01
    • 2013-12-24
    相关资源
    最近更新 更多