选择Wine Dynamic Programming

时间:2017-01-16 01:27:19

标签: python dynamic-programming

我最近开始学习动态编程,我发现了以下问题:

  

想象一下,你有一系列N种葡萄酒在一个架子上彼此相邻放置。为简单起见,让我们从左到右对葡萄酒进行编号,因为它们分别以1到N的整数站在货架上。第i款葡萄酒的价格是pi(不同葡萄酒的价格可能不同)。

     

因为葡萄酒每年变得更好,假设今天是第1年,第i年葡萄酒的价格将是y * pi,即y倍于当年的价值。

     

你想卖掉你所有的葡萄酒,但是你想要从今年开始每年出售一种葡萄酒。还有一个限制因素 - 每年你只允许卖掉货架上最左边或最右边的葡萄酒,你不能重新订购货架上的葡萄酒(即它们必须保持与开始时相同的顺序) )。

     

如果您以最佳顺序销售葡萄酒,您想知道,您可以获得的最大利润是多少。

来源:https://www.quora.com/Are-there-any-good-resources-or-tutorials-for-dynamic-programming-besides-the-TopCoder-tutorial/answer/Michal-Danil%C3%A1k?srid=3Otg

答案是自上而下的方法,我想创建一个自下而上的方法。以下是我定义问题的方法:

  

F(l,r)是从指定的左右索引中选择葡萄酒而产生的利润函数

     

INPUT:p是葡萄酒价格的一系列

     

F(l,r)= max(年* p [l] + F(l + 1,r)*(年+ 1),                  年* p [r] + F(l,r-1)*(年+ 1))

     

约束:l + r< = len(p)

我创建了以下Python代码来解决问题

def wine(Price):
    length = len(Price)
    DP = [[0] * (length+1) for _ in range(length+1)]

    for y in range(1,length+1): #Or can be range(length, 0, -1):
        for l in range(0, length):
            for r in range(length-1, -1, -1):
                if l+r <= length:
                    DP[l][r] = max(y * Price[l] + DP[l+1][r] * (y+1), \
                                    y * Price[r] + DP[l][r-1] * (y+1))
    return DP

我已将Price数组设置为[2,3,5,1,4]。消息来源表明Max Profit为50.但是,我无法用我编写的代码识别该值。有人可以用我的逻辑帮助识别问题吗?

3 个答案:

答案 0 :(得分:1)

您需要考虑的几点:

  • 在这种方法中,我们必须处理对角线和 三角形将为零
  • 此处的年份最初必须为最大年份,即 year = price.size()
  • 当前年份将使用公式计算(可以选择任何一个)。我用这个 公式: year = year-(j-i)//这对处理上三角很有用
  • 您必须正确使用DP阵列
int bottomUp(vector<int>price, int year, int start, int end) { int dp[100][100] = {0}; dp[start][start] = year*price[start]; for(int j=start+1; j<=end; j++) { for(int i=j; i>=0; i--) { int m = year-(j-i); int x = m*bottle[j] + dp[i][j-1]; int y = m*bottle[i] + dp[i+1][j]; dp[i][j] = max(x,y); } } return dp[start][end]; }

此处的代码返回可能的最大值 但是,我还粘贴了DP阵列外观的屏幕截图

Output DP Array

答案 1 :(得分:0)

要解决这个问题,我们需要以不同的顺序迭代数组。从左上角开始,我们按年获得以下值:

l

所以每年我们需要迭代一条对角线而不是rdef wine(price): length = len(price) DP = [[0] * (length+1) for _ in range(length+1)] # +1 for year0 in the corner for y in range(1,length+1): # y1, y2... yN for x in range(y+1): # intermediate values 0 to y l = x # which is used to calculate the real l, r # so, for the first year we get tuples (0, 1) and (1, 0) r = y - l # we just go along the diagonal # magic with l/r > 0 is used to prevent unwanted negative indexes # so, False and price[-1] = False and max(False, 4) = 4 DP[l][r] = max(l > 0 and DP[l-1][r] + y * price[l-1], \ r > 0 and DP[l][r-1] + y * price[-r]) return DP 上的双循环。所以,代码是:

>>> pprint(wine([2,3,5,1,4]))
[[0, 4, 6, 21, 33, 43],
 [2, 10, 13, 33, 48, 0],
 [8, 20, 25, 50, 0, 0],
 [23, 40, 50, 0, 0, 0],
 [27, 47, 0, 0, 0, 0],
 [47, 0, 0, 0, 0, 0]]

试运行:

{{1}}

答案 2 :(得分:0)

这里 i 和 j 分别表示给定 wines 数组的开始和结束索引。

重复:

  max(wines[i] * year + maxProfit( i + 1, j, year + 1), 
       wines[j] * year + maxProfit( i, j - 1, year + 1));

自上而下 DP

int maxProfit_td(int *wines, int i, int j, int year, int dp[][100])
{
    //  Base Case
    if (i > j)
        return 0;

    //Look Up
    if (dp[i][j] != 0)
        return dp[i][j];
    //  Recursive Case
    int op1 = wines[i] * year + maxProfit_td(wines, i + 1, j, year  + 1, dp);
    int op2 = wines[j] * year  + maxProfit_td(wines, i, j - 1, year  + 1, dp);

    return dp[i][j] = max(op1, op2);
}

自下而上 DP

int maxProfit_bu(int *wines, int n)
{
    int dp[100][100] = {0};
    // Wines array size
    int year = n;
    // Fill the diagonal elements i.e leaf nodes in case of recursion tree
    for (int i = 0; i < n; i++)
        dp[i][i] = year * wines[i];

    year--;

    // For remaining upper triangle
    for (int len = 2; len <= n; len++)
    {
        int start = 0, end = n - len;
        while (start <= end)
        {
            int cur = start + end - 1;
            dp[start][cur] = max(wines[start] * year + dp[start + 1][cur], 
                                  wines[cur] * year + dp[start][cur - 1]);
            start++;
        }
        year--;
    }

    return dp[0][n - 1];
}

函数调用

    int dp[100][100] = {0};
    cout << maxProfit_td(wines, 0, n - 1, 1, dp) << endl;
    cout << maxProfit_bu(wines, n) << endl;