【问题标题】:Dynamic Programming and the 0/1 knapsack动态规划和 0/1 背包
【发布时间】:2014-04-28 08:10:32
【问题描述】:

我在理解动态编程时遇到了一些麻烦,尽管我已经阅读了很多试图理解的资源。

我了解使用斐波那契算法给出的动态编程示例。我理解如果你使用分而治之的方法,你最终会多次解决一些子问题,而动态编程通过解决那些重叠的子问题来解决这个问题,但只解决一次(并将它们存储起来以供将来参考) .但是,我在课堂上以 0/1 背包问题为例介绍了动态编程,但我并不真正理解该示例,或者它如何说明动态编程,或者它与斐波那契示例有何相似之处.

以下是与之相关的幻灯片:

在最后一张幻灯片之前,我主要了解发生了什么,上面写着 f(i,y) = max{....}

我到底找到了什么最大值?为什么我发现任何东西的最大值?最重要的是,这与动态规划有什么关系?我不理解这种关系,就像我在谈到斐波那契示例时所做的那样。老实说,我不知道这个背包问题与动态规划有什么关系,因为它甚至看起来都无法与使用斐波那契示例来说明动态规划相提并论。就像我没有看到任何相似之处或任何东西,这对我来说真的没有多大意义

【问题讨论】:

标签: algorithm dynamic-programming knapsack-problem


【解决方案1】:

动态编程只是根据更简单的子问题来定义问题。

在斐波那契的情况下,我们根据两个较小的术语来定义问题。

在这种情况下,我们根据包含较少项目和可能较小容量的子问题来定义具有一定数量的项目和一些容量的问题。

我们开始计算最多 1 个项目和每个容量的利润。然后我们计算最多 2 个项目和每个容量的利润。然后我们最多对 3 个项目执行此操作,然后是 4 个,依此类推。由于我们已经根据具有较少项目的子问题定义了一个问题,因此我们可以简单地查找我们已经计算的内容,以确定具有 2、3、4 等项目的任何值。

将其视为物理 2D 网格可能会有所帮助,您可以在其中从一个方向填充值到另一个方向,并且每次您只查看已填充所有值的方向。

存在重叠的子问题,因为在一种情况下我们使用相同的容量,而在另一种情况下我们使用的容量较小。较小的容量有时会匹配检查相同容量的不同子问题。也就是说f(i+1, j) 处理一个问题将等于f(i+1, y - w_i) 处理另一个问题。例如,您可以看到f(11, 5) 出现在两个地方:

f(10, 8) = max(f(11, 8), f(11, 5) + 77)   // w_i = 3
f(10, 5) = max(f(11, 5), f(11, 2) + 77)

在这种情况下,我们已经为每个 X 计算了 f(11, X),因此我们可以查找这些值。

我确实觉得有点令人困惑,我们在增加 i 方面定义问题,就像在 f(i, j) = ...f(i+1, X)... 中一样,f(n, X) 因此最多包含 1 个项目,而不是使用减少 i 并具有f(1, X) 最多 1 项。但这只是语义,不会以任何方式改变问题。

技术细节说明

f(i,y) 是包含从 in 的项目子集的最大利润,容量为 y

现在我们可以将其定义为包含或排除项目i,然后获得项目i+1n 的最大利润。

当我们排除项目i时,这不会改变重量,所以我们可以只看相同容量的最大利润,即f(i+1, y),利润也没有变化。

当我们包含项目i时,这会改变权重,特别是通过项目i的权重,即w_i,因此我们必须查找f(i+1, y - w_i)。但是接下来我们也从项目i获得了利润,所以我们需要加上它的利润,即p_i

现在,既然我们想要最大的利润,我们必须找到这两个值的最大值,给我们:

f(i, y) = max{f(i+1, j), f(i+1, y - w_i) + p_i}

如果您仍然无法理解它,我建议您为自己构建一个示例来解决 - 再多的解释都无法看到它实际工作,并使用它来获得一些直觉,了解我们为什么要这样做我们的方式。

【讨论】:

  • 所以当你说我们是根据包含 less 个项目和可能更小的容量的问题来定义它时,在这个特定的例子中,它从最后一个项目倒退到第一个,根据我们对n的决定来确定物品n-1是否进入背包,我们根据n-1和n是否进入来确定物品n-2是否进入,等等?例如,如果有 3 个项目,我们首先会执行 f(1,y) = max (f (2, y), f(2, y-w_1) + p_1 },但实际上我们不会得到直到我们到达第 n 个项目,然后它就会倒退?@Dukeling
  • 这是否类似于递归,其中基本情况是第 n 项,它返回值(或决策)直到返回到第 1 项?
  • 如果我刚才描述的是正确的,那是否是使用记忆或“自上而下”方法进行动态编程的一个例子?
  • 这太令人困惑了。我构建了以下示例:w = [3, 2, 10] 和 p = [9, 5, 1],总容量为 11,n= 3 个项目。所以我们从 f(n,y) 开始,即 f(3, 11).. 因为 w_3
  • @codemania23 我在答案中添加了更多细节。
【解决方案2】:

我到底找到了什么最大值?

f 是你放入背包的所有物品所带来的利润之和。在第一阶段,有两种可能:

  • 您将第 i 件物品放入背包,然后解决所有剩余物品的问题,从您的最大重量中减去第 i 件物品的重量,
  • 您没有将第 i 项放入背包,而是解决了所有剩余物品的问题。这是一个您已经解决的子问题,因为您正在向后工作,因此与动态编程的联系应该在那里变得明显。

解决方案是带来最高利润的选项,因此是最大的。

【讨论】:

  • 你到底是如何逆向工作的?如果您从第 i 项开始并转到第 i + 1 项,那似乎不会倒退@Zoyd
  • 建议的解决方案从 i = n 到 i = 1 工作。这就是我所说的“向后”工作,而不是基本情况为 i = 1 的递归算法。我想我可以已经说得更清楚了。 @FrostyStraw
  • @Zoyd,请解释重叠子问题在哪里。 ???我只是把它写在纸上,在这里我似乎没有发现任何重叠的问题。
猜你喜欢
  • 2018-03-27
  • 2022-01-13
  • 1970-01-01
  • 2018-04-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-19
相关资源
最近更新 更多