C++ 葡萄酒选择动态规划

C++ 葡萄酒选择动态规划,c++,algorithm,recursion,dynamic-programming,C++,Algorithm,Recursion,Dynamic Programming,这是一个非常著名的实现DP的例子,但由于某些原因,我不能完全理解这个算法,并且我已经在为计算奥运会做准备了很长一段时间 想象一下,你有一个N种葡萄酒的集合,它们彼此挨着放在桌子上 架子。为了简单起见,让我们将葡萄酒从左到右编号为 他们站在架子上,整数从1到N, 分别地第i种葡萄酒的价格是不同价格的pi 葡萄酒可以是不同的 因为葡萄酒一年比一年好,假设今天就是一年 1,在y年,第i种葡萄酒的价格为y*pi,即y乘以 本年度的价值 你想卖掉你所有的葡萄酒,但你想卖得一丝不苟 从今年开始,每年一杯葡萄

这是一个非常著名的实现DP的例子,但由于某些原因,我不能完全理解这个算法,并且我已经在为计算奥运会做准备了很长一段时间

想象一下,你有一个N种葡萄酒的集合,它们彼此挨着放在桌子上 架子。为了简单起见,让我们将葡萄酒从左到右编号为 他们站在架子上,整数从1到N, 分别地第i种葡萄酒的价格是不同价格的pi 葡萄酒可以是不同的

因为葡萄酒一年比一年好,假设今天就是一年 1,在y年,第i种葡萄酒的价格为y*pi,即y乘以 本年度的价值

你想卖掉你所有的葡萄酒,但你想卖得一丝不苟 从今年开始,每年一杯葡萄酒。还有一个限制-对 每年你只能出售最左边的或最左边的 货架上最右边的葡萄酒,不允许您重新订购 货架上的葡萄酒,即它们必须保持原来的顺序 一开始

你想知道,如果你愿意,你能得到的最大利润是多少 按最佳顺序出售葡萄酒


<> P>和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]);
}

我遇到的主要困惑与我们使用的最大值函数有关。据我所知,递归利润函数计算如果我们在去年销售葡萄酒1,那么总利润是多少,如果我们在去年销售葡萄酒2,那么总利润是多少。因此,假设葡萄酒1的总利润更大,如果它是在以后几年出售的,那么我们是否应该保留葡萄酒1,因为它将在以后为我们带来更多利润,并出售葡萄酒2,因为它的利润将低于葡萄酒1,还是有什么我没有得到的

这个递归解决方案就是检查所有可能的场景并返回最大值。这是一个玩具分析,2个可能的条件选择最右边或最左边。每一步,你都可以选择其中一个,这样你的算法在O2^n下工作,这是非常慢的。马克斯在这里只是选择一个更大的,没有什么特别的。并且此解决方案不是动态的,您可以使用memonization:

也可以这样写

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,那么总利润是多少,如果我们在去年销售葡萄酒2,那么总利润是多少。因此,假设葡萄酒1的总利润更大,如果在以后几年销售,那么,我们不应该保留葡萄酒1,因为它以后会为我们带来更多的利润,而销售葡萄酒2,因为它的利润会低于葡萄酒1吗


不,这完全是错误的,这是一个递归算法,它计算如果在第一年销售葡萄酒1或去年销售葡萄酒1会发生什么,想象你有10个葡萄酒最大值将在下一个10年计算并返回答案

有一个带记忆的解决方案,但这对我来说毫无疑问,嗯,动态规划是一种记忆;如果你忽略这一点,它只是一个效率极低的算法。@yakop本身对DP没有问题,但是如何得到这个问题的递归公式。因此,他说回忆录与他的具体问题无关是正确的。
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