我可以使用动态规划来解决这个问题吗?

Posted

技术标签:

【中文标题】我可以使用动态规划来解决这个问题吗?【英文标题】:Can I use dynamic programming to solve this? 【发布时间】:2016-01-24 21:41:14 【问题描述】:

我对动态编程的经验很少。我用它解决了一个 DNA 比对问题、一个基本的背包问题和一个简单的寻路问题。我理解他们是如何工作的,但这并不是我觉得绝对舒服的事情。

我有一个问题让我想起了 0-1 动态规划,但这些差异让我感到厌烦,我不确定我是否仍然可以使用这种技术,或者我是否必须满足于递归方法。

假设我有一个项目列表,每个项目都有不同的价值、重量和成本。每个项目可能不止一个。

假设我必须从那些最有价值的物品中选择一个组合,但要保持在重量和成本的限制范围内。到目前为止,我已经描述了几乎有两个约束的背包问题。但这里有区别:

所选项目的价值会根据我在组合中的数量而变化。

假设每个项目都有一个与之关联的功能,它告诉我一组这些项目对我来说价值多少。它是一个基本的线性函数,例如 value_of_item = -3(该项目的数量)+ 50

所以,如果我在一个组合中有 1 件,那么它对我的价值是 47。如果我有 2 个,那么它们对我来说每个只值 44。

如果我为此使用动态编程表,那么对于每个单元格,我都必须回溯以查看该项目是否已经在当前组合中,从而使 DP 毫无意义。但也许有办法重新构建问题,以便我可以利用 DP。

希望这是有道理的。

另一种方法是在成本和重量的限制内生成每个物品组合,计算每个组合的价值,选择最有价值的组合。即使是 1000 个项目的列表,这将是一个昂贵的搜索,而且我会反复计算。我想找到一种方法来利用 DP 的优势。

【问题讨论】:

DP 的本质是执行计算,然后允许快速查找该结果以供将来计算。这需要在表示输入条件的某个唯一数字与该组条件的计算成本之间进行映射。如果我有 2Red 和 3Green 以及 4Blue,我可以将所有可能的组合唯一编号为:r=#of red, g=#of green, b=#of blue, id = r*(3*4) + g*4 + 乙。我可以使用 id 来查找缓存的计算。 【参考方案1】:

如果你的函数的形式是

value(x, count) = base(x) - factor(x) * count, factor(x) > 0,

那么您可以通过拆分物品将问题简化为标准背包:

x -> x_1 to x_max_count
value_new(x_i) = value(x, i)
weight(x_i) = weight(x)

现在您可以轻松地验证新问题的最佳解决方案没有使用某些项目x_j,而无需使用带有 i x_i。

矛盾证明:假设存在这样一个最优解 S,它使用x_j,但不是x_i,j > i。然后有一个替代解决方案 S' 使用 x_i 而不是 x_j。由于 j > i,

value_new(x_j) = value(x, j) 
               = base(x) - factor(x) * j 
               < base(x) - factor(x) * i
               = value(x, i)
               = value_new(x_i)

因此 S' 的值比 S 高,我们遇到了矛盾。

此外,我们可以允许factor(x) = 0,这对应于一个标准的背包物品。

但是如果有表单的约束

value(x, count) = base(x) + factor(x) * count

其中factor(x) 是任意值,上述解决方案不再有效,因为最后一项将是具有最大值的一项。也许对 DP 进行一些复杂的修改可能允许您使用此类约束,但我没有看到对问题本身进行任何修改以立即使用 DP。

本主题的一些研究(更笼统):

http://dept.cs.williams.edu/~heeringa/publications/knapsack.pdf http://clweb.csa.iisc.ernet.in/vsuresh/Kamesh-PLKP.pdf

【讨论】:

以上是关于我可以使用动态规划来解决这个问题吗?的主要内容,如果未能解决你的问题,请参考以下文章

寻找解决这个动态规划问题的提示

用动态规划求解分数背包问题

浅谈动态规划(个人理解)

动态规划的记忆法或制表法

动态规划

使用动态规划求解最小分配