【问题标题】:How does DP helps if there are no overlapping in sub problems [0/1 knapsack]如果子问题没有重叠,DP如何帮助[0/1背包]
【发布时间】:2016-12-25 20:53:51
【问题描述】:

考虑以下典型背包问题的输入。

V = [10,8,12]
W = [2,3,7]
i =  1,2,3
C = 10

我尝试使用记忆递归来解决这个示例,但没有发现重叠子问题。

递归过程的签名:

knapsack(int c, int i) 

最初称为knapsack(10,1)

解决方法如https://www.youtube.com/watch?v=6h6Fi6AQiRMhttps://www.youtube.com/watch?v=ocZMDMZwhCY中所述。

动态规划如何帮助降低此类背包样本的时间复杂度?基于回溯搜索,即 2 的 n 次幂 [忽略修剪,如果应用了修剪,那么解决方案的复杂性将会降低,并且 DP 不会比非记忆递归解决方案更好]

** 上面的示例中是否确实缺少子问题的重叠,或者我遗漏了什么?**

【问题讨论】:

  • 已知背包问题是 NP 完全问题或 NP 困难问题,具体取决于确切的公式,因此找到一个没有指数运行时间的算法将是 very surprising indeed
  • DP 是允许在多项式时间内解决指数问题的技术的通用术语。记忆是 DP 中使用的一种技术,但不是用于 0/1 背包问题的技术。
  • @user3386109 感谢您的回答,我查看了 wiki 链接,我之前也看过这个解决方案。但正如我的问题中提到的视频链接中的教授所说,recurrence with memoization 只是解决问题的另一种观点,如果我们希望使用涉及表格的自下而上的方法,或者我们使用带有 memo 的recurrence,这并不重要。跨度>
  • 用于动态编程 重叠子问题是必须具备的,但我无法在我的示例中找到。如果您能帮我为上述示例定义它,那将对我有所帮助。

标签: algorithm recursion dynamic-programming memoization knapsack-problem


【解决方案1】:

如果没有一个权重与其他任何权重相加并且容量足够大以包含总权重,则带有记忆的递归解决方案的运行时间可以接近 2^n

不过,动态编程解决方案是 O(c*n)。这是容量而不是项目数的多项式。

在你的例子中n=3c=10,所以2^n = 8c*n = 30。这里c*n 大于2^n,所以 dp 解决方案没有帮助。如果您的项目数量较多且容量较小,则 dp 解决方案会更好。这些是 dp 解决方案可以很好地处理的约束类型。

【讨论】:

    【解决方案2】:

    0/1 背包问题有一个pseudo-polynomial-time solution。该解决方案的运行时间是O(nW),其中n 是可供选择的物品数量,W 是背包可以容纳的重量。运行时间被描述为多项式,因为W 不是n 的函数。

    是吗?给定n 项目列表(按重量和价值),存在一个项目的最大重量,称为k。 (最大重量可以在 O(n) 时间内确定。)如果W 大于或等于kn,那么问题很简单,所有物品都装在背包里。因此,我们只需要考虑W < kn的情况。所以为了复杂度分析的目的,W可以表示为n的函数。

    鉴于nW <= k n^2,算法的运行时间为O(k n^2)

    现在,听众中的学究们会(正确地)争辩说这仍然是伪多项式时间,因为kn 之间没有明确的关系。但问题的任何具体陈述(按权重和值列出项目)都必须​​在问题陈述本身中有一个明确的 k 常量值。

    理论说得够多了。我们如何将此应用于问题中的示例。

    • n 显然是 3
    • k 显然是 7

    因此,预测的运行时间是O(kn^2) = O(7x3x3) = 63。但是预测的指数运行时间(没有DP)是O(2^n) = O(2^3) = 8.

    您的示例存在问题。 Big-O 分析描述了n 大值的算法的渐近行为。它几乎没有告诉你n 的小值的性能。如果n的值比2^n < k n^2小,那么就不能指望DP会提高算法的运行时间,或者根本没有任何效果。

    您的挑战是找到2^n > k n^2 的示例,并且您仍然没有重叠子问题。

    【讨论】:

      【解决方案3】:

      DP 对您的特定问题实例完全没有帮助。但总的来说,即在所有可能的输入实例中,它永远不会比纯递归解决 更多 个子问题,而且在许多实例上它解决的问题要少得多。 这就是为什么DP很好。

      您的所有 DP 公式保证是它可以通过解决最多 n(c+1) 子问题来解决问题的任何实例,实际上它对于您的示例也是如此:这里 n = 3 和c = 10,它通过解决 14

      同样,纯递归解决方案保证它可以通过解决最多2^n 子问题来解决问题的任何个实例。

      您似乎认为 DP 算法应该比递归算法更快地解决每个问题实例,但事实并非如此,没有人提出这种说法。存在没有重叠子问题的实例(如您的实例),对于这些实例,DP 使用与递归解决方案完全相同数量的子问题来解决问题。这并没有说明这两种算法的行为一般。一般来说,DP 最多使用与递归解决方案一样多的子问题来解决每个问题,有时甚至更少——因为确实存在递归算法需要多次解决同一个子问题的问题实例。

      简而言之:DP 永远不会比递归差,并且在最坏的情况下优于递归。这确实意味着它在每个实例上都更好。

      【讨论】:

      • 回答到了重点。完美,这就是问题中提出的问题。
      猜你喜欢
      • 1970-01-01
      • 2020-03-19
      • 1970-01-01
      • 2021-02-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多