【发布时间】:2017-10-29 08:02:53
【问题描述】:
所以这是一个非常有名的实现DP的例子但是由于某种原因我不能完全理解算法,并且我已经坚持了很长一段时间(准备计算奥林匹克)。问题如下
想象一下,你有 N 种葡萄酒并排放置在 一个架子。为简单起见,让我们从左到右将葡萄酒编号为 他们站在架子上,拿着从 1 到 N 的整数, 分别。第 i 种酒的价格是 pi(不同的价格 葡萄酒可以不同)。
因为葡萄酒每年都在变好,假设今天是一年 1,在第 y 年,第 i 个酒的价格为 y*pi,即 y 乘以 当前年份的值。
你想卖掉你所有的酒,但你想卖的正是 从今年开始,每年一款酒。另一个约束 - on 每年您只能出售最左边的或 货架上最右边的酒,您不得重新订购 货架上的葡萄酒(即它们必须保持与它们相同的顺序 一开始)。
你想知道,如果你能获得的最大利润是多少 以最佳顺序出售葡萄酒
并且给出了 c++ 中的解决方案(有一个带有记忆的解决方案,但这对我来说几乎不重要):
int p[N]; // read-only array of wine prices
// year represents the current year (starts with 1)
// [be, en] represents the interval of the unsold wines on the shelf
int profit(int year, int be, int en) {
// there are no more wines on the shelf
if (be > en)
return 0;
// try to sell the leftmost or the rightmost wine, recursively calculate the
// answer and return the better one
return max(
profit(year+1, be+1, en) + year * p[be],
profit(year+1, be, en-1) + year * p[en]);
}
我的主要困惑与我们正在使用的 max() 函数有关。据我所知,如果我们在去年销售葡萄酒 1,递归利润() 函数会计算总利润是多少,如果我们在去年卖了酒 2,总利润将是多少。所以假设酒 1 的总利润更大,如果它在后几年出售,那么我们是否应该实际保留酒 1(因为它会卖我们稍后会获得更多利润)并出售葡萄酒 2(因为它的利润会低于葡萄酒 1),还是有什么我没有得到的?
【问题讨论】:
-
“有一个memoization的解决方案,但我怀疑这并不重要” 嗯,动态编程是一种memoization;如果你跳过它只是一个非常低效的算法。
-
@Yakk OP 本身对 DP 没有问题,但在如何获得这个问题的递归公式方面。因此,当他说记忆对他的具体问题无关紧要时,他是对的。
标签: c++ algorithm recursion dynamic-programming