在16.1 An activity-selection problem的Introduction to Algorithm,对于这个问题的动态规划溶液给出
16.1 An activity-selection problem
Introduction 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)为空,则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)
S(i, j)
a(i)
a(j)
c[i, j]
但是,我在考虑另一个更简单的解决方案
c[i] = max { c[i - 1], c[f(i)] + 1 }
其中f(i)给出与活动兼容a(i)并具有最大 完成时间并在 开始 之前完成 的活动 。 a(i)
f(i)
这样行吗?如果是,为什么作者提供这种复杂的解决方案。如果没有,我想念什么?
我认为您缺少设计dp解决方案的许多细节。
设计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
Greedy versus DP
TL; DR:您的解决方案是正确的,因为它基本上是解决问题的贪婪方法,当然,它比本书中给出的DP解决方案容易得多,因为这正是本书所要说明的重点。 引用本书P.382的话:…当贪婪的解决方案足够时,可能会试图为问题生成dp解决方案,或者可能会错误地认为贪婪的解决方案就已足够…当需要dp解决方案时…