小编典典

活动选择的动态编程解决方案

algorithm

16.1 An activity-selection problemIntroduction to Algorithm,对于这个问题的动态规划溶液给出

如果S(i,j)为空,则c [i,j] = 0

如果S(i,j)不为空,则c [i,j] = max {c [i,k] + c [k,j] + 1}

其中S(i, j)表示在活动a(i)结束之后a(j)开始并且在活动开始之前结束的活动集合,并c[i, j]表示该集合的最佳解决方案的大小S(i, j)

但是,我在考虑另一个更简单的解决方案

c[i] = max { c[i - 1], c[f(i)] + 1 }

其中f(i)给出与活动兼容a(i)并具有最大 完成时间并在 开始 之前完成 的活动 a(i)

这样行吗?如果是,为什么作者提供这种复杂的解决方案。如果没有,我想念什么?


阅读 321

收藏
2020-07-28

共1个答案

小编典典

我认为您缺少设计dp解决方案的许多细节。

  1. 初始值是多少?
  2. 基本情况是什么?
  3. 如果有多个活动在相同的完成时间下与a(i)兼容,该怎么办?

设计dp解决方案时,所需的属性之一是最佳子结构

特定状态(即c [i])的计算顺序很重要,只能通过其子问题来计算。您的解决方案不满足此要求,因为当您计算c [i]时,您必须首先使用j = f(i)来计算c
[j],让我们假设j> i(甚至j = i + 1),然后您必须先计算c [i]才能计算c [j]!所以c [i]取决于c [j],而c [j]取决于c
[i] ==>不正确

与这个问题非常相似的另一个例子是矩阵链多重复制

您可能想看看:)

编辑: 看到您编辑了问题之后,这是我的回复:

假设您可以在合理的时间内预先计算f(i)(显然可以),那么您的解决方案是正确的,因为 它是 其他答案告诉您 的贪婪解决方案

从字面上来讲,它起作用的原因很简单

until the i-th activity, you either choose activity i (thats the c[f(i)]+1 part) or not choose it (the c[i-1]) part

您也可以尝试构造形式证明,通常可以通过矛盾来证明贪婪方法的正确性(粗略地说,您可以尝试了解为什么 除了c
[i-1]之外不可能有更大的集合如果您不选择活动i,则类似于选择活动i的情况

要回答你关于为什么笔者展示了DP解决的问题,我认为这是编程方面的,但是我的想法是在用户试图展示两种不同的方式来解决问题,而且在这里说明一个想法:
给定一个问题,可以用贪婪的方法解决,也可以用dp解决,但是这很麻烦。

然后作者尝试帮助读者认识Greedy和dp之间的区别,因为它们与新学习者非常相似。这就是为什么笔者先给DP解决方案展现痛苦,那么贪婪的解决方案,最后一个段落Greedy versus DP中的页382

TL; DR:您的解决方案是正确的,因为它基本上是解决问题的贪婪方法,当然,它比本书中给出的DP解决方案容易得多,因为这正是本书所要说明的重点。
引用本书P.382的话:…当贪婪的解决方案足够时,可能会试图为问题生成dp解决方案,或者可能会错误地认为贪婪的解决方案就已足够…当需要dp解决方案时…

2020-07-28