在16.1 An activity-selection problem
的{{1}}中,针对此问题的动态编程解决方案为
如果S(i,j)为空,则c [i,j] = 0
如果S(i,j)不为空,c [i,j] = max {c [i,k] + c [k,j] + 1}
其中Introduction to Algorithm
表示在活动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)
开始之前完成。
这会有用吗?如果是,为什么作者提供这种复杂的解决方案。如果没有,我错过了什么?
答案 0 :(得分:2)
我认为您缺少设计dp解决方案的许多细节。
在设计dp解决方案时,所需的属性之一是optimal substructure
特定状态(即c [i])的计算顺序很重要,它只能通过其子问题计算。你的解决方案不符合这个要求,因为当你计算c [i]时,你必须首先使用j = f(i)计算机c [j],我们假设j>我(或甚至j = i + 1),那么你必须在计算c [j]之前计算c [i]!所以c [i]取决于c [j]而c [j]取决于c [i] ==>不正确
另一个与此问题非常相似的例子是Matrix chain mutiplication
您可能需要查看:)
修改强> 看到你编辑问题后,这是我的回答:
假设你可以在合理的时间内预测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,类似于你选择活动的情况我)
要回答关于为什么作者演示dp解决方案的问题,我认为这不是编程上下文,但我的想法是用户试图演示两种不同的方法来解决问题,并在此处说明一个想法:< strong>给出一个可以通过贪心方法解决的问题,它也可以通过dp来解决但是它是过度的。
然后作者试图帮助读者认识到Greedy和dp之间的区别,因为它们与新学习者非常相似。这就是为什么作者首先给出DP解决方案以显示痛苦,然后是贪婪的解决方案,最后是Page 382
中的Greedy versus DP
段
所以TL; DR:你的解决方案是正确的,因为它基本上是解决问题的贪婪方法,当然它比书中给出的DP解决方案容易得多,因为这是本书的重点我想说明一下。 从P.382的书中引用:......当一个贪婪的解决方案足够时,人们可能会试图为问题生成一个dp解决方案,或者一个人可能错误地认为贪婪的解决方案足够......当一个dp解决方案是必需的......
答案 1 :(得分:2)
这会有用吗?
是的,这也会奏效。
作者为何提供这种复杂的解决方案。
这不是他们提出的解决方案,而是问题分析的一部分。在你引用的等式之后的下一段中,作者说:
但我们会忽略另一个重要特征 我们可以充分利用的活动选择问题。
最终解决方案(Greedy-Activity-Selector)与您的相似,但更简单。
根据我的理解,他们的观点是DP解决方案几乎可以机械地构建(如第15.3章所述),而不考虑该特定问题的细节,但提出更好的算法需要深入了解超出最优子结构的问题。
你的解决方案依赖于定理16.1,但是一旦定理得到证实,创建另一个DP算法就没有意义了,因为你已经足够了解这个问题来创建一个更简单的贪婪算法。