所以这是实施DP的一个着名的例子,但由于某种原因我无法完全理解算法,并且我已经坚持了很长一段时间(准备计算奥林匹克运动会)。问题如下
想象一下,你有一系列N种葡萄酒紧挨着放在一起 一个架子。为简单起见,让我们将葡萄酒从左到右编号为 他们站在架子上用1到N的整数, 分别。第i款葡萄酒的价格是pi(价格不同 葡萄酒可以是不同的)。
因为葡萄酒每年变得更好,所以今天就是今年 1,在第y年,第i个葡萄酒的价格将是y * pi,即y倍 当年的价值。
你想卖掉你所有的葡萄酒,但你想要卖得很好 每年一杯葡萄酒,从今年开始。还有一个限制因素 每年你只能卖出最左边或者最左边的 最右边的葡萄酒在架子上,你不能重新订购 货架上的葡萄酒(即它们必须保持原样相同的顺序) 在开始)。
您想了解一下,如果您能获得的最大利润是多少 以最佳顺序出售葡萄酒
并且给出了c ++中的解决方案(有一个带有memoization的解决方案,但这对我的疑问几乎不重要):
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()函数有关。据我所知,递归profit()函数计算如果我们在去年销售葡萄酒1时的总利润和如果我们去年出售葡萄酒2,那么总利润是多少。所以说葡萄酒1的总利润更大,如果它在晚些时候出售,那么我们不应该实际保留葡萄酒1(因为它我会在以后获取更多的利润)并出售葡萄酒2(因为它可以获得低于葡萄酒1的利润),或者是否有一些我没有得到的东西?
答案 0 :(得分:1)
这种递归解决方案是只检查所有可能的场景并返回最大值。这是一个玩具分析,2个可能的条件选择最右边或最左边。 Everystep,你可以选择其中一个,这样你的算法就可以在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
答案 1 :(得分:0)
据我所知,递归profit()函数计算去年我们卖葡萄酒1的总利润是多少,如果我们去年卖了葡萄酒2,那么总利润是多少。所以让我们说葡萄酒1有更大的总利润,如果它在晚些时候出售,那么我们不应该实际保留葡萄酒1(因为它会在后来获得更多的利润)并出售葡萄酒2(因为它会获得利润少于葡萄酒1)
没有完全错误,它是一个递归算法,它计算如果在第一年卖葡萄酒1或在第一年葡萄酒“最后”发生什么,想象你有10葡萄酒max()将计算未来10年并返回答案< / p>