葡萄酒选择动态规划
Posted
技术标签:
【中文标题】葡萄酒选择动态规划【英文标题】:Wine Selection Dynamic Programming 【发布时间】: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 没有问题,但在如何获得这个问题的递归公式方面。因此,当他说记忆对他的具体问题无关紧要时,他是对的。 【参考方案1】:这个递归解决方案是检查所有可能的场景并返回它的最大值。这是一个玩具分析,2 个可能的条件选择最右边或最左边。每一步,你都可以选择其中一个,这样你的算法就可以在 O(2^n) 上运行,这真的很慢。 max() 在这里只是选择更大的,没有什么特别的。而且这个解决方案不是动态的,你可以使用 memoization:https://en.wikipedia.org/wiki/Memoization。
return max(
profit(year+1, be+1, en) + year * p[be],
profit(year+1, be, en-1) + year * p[en]);
也可以这样写。
int max_from_left = profit(year+1, be+1, en) + year * p[be]
int max_from_right = profit(year+1, be, en-1) + year * p[en]);
if( max_from_left > max_from_right)
return max_from_left
else
return max_from_right
【讨论】:
【参考方案2】:据我所知,递归的利润()函数计算如果我们在去年卖酒 1 的总利润是多少,如果我们在去年卖酒 2 的总利润是多少。所以假设葡萄酒 1 的总利润更大,如果它在后期出售,那么我们是否应该实际保留葡萄酒 1(因为它会在以后为我们带来更多利润)并出售葡萄酒 2(因为它会获得利润小于酒 1)
不,它完全错误,它是一个递归算法,它计算如果在第一年销售葡萄酒 1 或在第一年“最后”销售葡萄酒会发生什么,想象你有 10 个葡萄酒 max() 将计算下一个 10 年并返回答案
【讨论】:
以上是关于葡萄酒选择动态规划的主要内容,如果未能解决你的问题,请参考以下文章