葡萄酒选择动态规划

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 年并返回答案

【讨论】:

以上是关于葡萄酒选择动态规划的主要内容,如果未能解决你的问题,请参考以下文章

算法动态规划 ⑧ ( 动态规划特点 )

关于解题思想选择动态规划还是贪心

动态规划中的0-1背包问题怎么去理解?要求给出具体实例和详细步骤。。。

《数据结构与算法之美》27——初识动态规划

动态规划总结

使用动态规划在资金有限的情况下选择活动