用动态编程修补棋盘格

时间:2013-09-23 04:21:30

标签: python algorithm dynamic-programming

我正在尝试自学动态编程,并从麻省理工学院遇到了这个问题。

我们给出了一个有4行n列的棋盘格 每个方块都有一个整数。我们也给了一组2n鹅卵石,我们想要 将部分或全部放在棋盘上(每个鹅卵石可以放在一个正方形上) 以便最大化鹅卵石覆盖的正方形中的整数之和。有 一个约束:对于一个合法的鹅卵石放置,其中没有两个可以水平或 垂直相邻的正方形(对角线邻接是可以的)。

(a)确定任何列中可能出现的合法模式的数量(孤立地忽略 相邻列中的鹅卵石)并描述这些模式。 如果可以将两个模式放在相邻列上以形成合法放置,则调用两个模式兼容。 让我们考虑由第一个k列1 k n组成的子问题。每个子问题都可以 被赋予一个类型,即最后一列中出现的模式。

(b)使用兼容性和类型的概念,给出一个O(n)时动态规划算法来计算最佳位置。

好的,对于第一部分:有8种可能的解决方案。

对于b部分,我不确定,但这是我要去的地方: SPlit成子问题。假设我在n。 1.通过列0,...,i来定义Cj [i]为最佳值,使得列i具有模式类型j。 2.为每种模式类型创建8个单独的n个元素数组。

我不知道从哪里开始。我意识到网上有这个问题的解决方案,但解决方案对我来说似乎不太清楚。

1 个答案:

答案 0 :(得分:3)

你走在正确的轨道上。当您检查每个新列时,您将最终计算到目前为止所有可能的最佳分数。

假设您构建了兼容性列表(2D数组)并将其称为 L i [y] ,以便对每个模式 i 有一个或多个兼容模式 L i [y]

现在,您检查列 j 。首先,您为每个模式 i 计算该列的孤立分数。称之为 S j [i] 。对于每个模式 i 和兼容 模式 x = L i [y] ,你需要最大化总分 C j 这样 C j [x] = C j-1 [i] + S j [x] 。这是一个简单的数组测试和更新(如果更大)。

此外,您还可以存储导致每个分数的pebbling模式。当您更新 C j [x] 您将其得分从其当前值增加时)时,请记住导致其的初始和后续模式更新为 P j [x] = i 。这表示“模式 x 给出了最好的结果,给出了前面的模式 i ”。

完成所有操作后,只需找到最高分 C n [i] i 模式。然后,您可以使用 P j 进行回溯,以从每个导致此结果的列中恢复出来的pebbling模式。