对Spoj的问题TRT(奶牛治疗)进行dp处理的最佳方法是什么?

时间:2019-06-29 09:48:59

标签: c++ dynamic-programming

FJ已为那些因提供大量牛奶而赚钱的母牛购买了N(1 <= N <= 2000)种美味佳肴。 FJ每天卖出一种零食,并希望在给定的时间内使自己获得的收益最大化。零食很有趣,原因有很多:

零食编号为1..N,并按顺序存储在长文件中的单个文件中,长文件两端均打开。在任何一天,FJ都可以从零食的任一端检索一种零食。 像美酒和美味的奶酪一样,这些美食会随着年龄的增长而提高,并且价格更高。 对待并不统一:一些更好并且具有更高的内在价值。零食i的值为v(i)(1 <= v(i)<= 1000)。 母牛为更长寿的食物支付更高的价格:母牛为a岁的食物支付v(i)* a。 给定每个零食的值v(i)在其包装盒中按索引i的顺序排列,如果FJ最佳订购它们,FJ可获得的最大价值是什么?

第一款在第1天出售,年龄a = 1。随后的每一天将年龄增加1。

输入 第1行:单个整数N

第2..N + 1行:第i + 1行包含处理v(i)的值

输出 通过出售零食可以达到FJ的最大收入

示例 输入: 5

1 3 1个 5 2

输出: 43

解决此问题的dp的基本方法是什么?我该如何处理dp矩阵中的年龄...?我想到的唯一方法是递归方法...我是DP的新手,已经做了一些基本的dp问题,但是这超出了我的脑筋...这是我到目前为止尝试过的

int give(int a[],int x,int y,int age)
{

if(x==y) return age*a[x];

return max(age*a[x]+give(a,x+1,y,age+1),age*a[y]+give(a,x,y-1,age+1));

}

x =起始索引,首次调用时从0开始,y =最后一个索引,n-1,age = 1

1 个答案:

答案 0 :(得分:0)

要观察的第一件事是,当前状态不取决于我们从何处获取美食的历史。我们唯一关心的是,我们从左侧获得了几次治疗,而从右侧获得了几次治疗。

因此状态只能用2个数字编码:左偏移和右偏移。

f(i,j)是直到我们出售当前举动之前我们仍然可以获得的金额。我们知道那里已经从行中提取了i+j个对象,因此年龄也为i+j

因此,我们只需要检查我们要从哪个位置开始,然后选择更好的位置即可。好吧,如果我们从左边选择一种零食,我们获得的金额将为

cost * time + f( i + 1 , j ) = cost * (i + j) + f( i + 1 , j )

如果我们从右边获取的金额,其公式非常相似

cost_right * (i + j) + f( i , j + 1 )

因此,我们可以知道f(i+1,j)f(i,j+1)来计算f(i,j)

这可以通过使用动态编程来完成,方法是存储大小为n*n的2D数组,如果-1未知,则存储f(i,j),或者如果f(x,y)的值则存储{我们都知道。然后,您可以简单地更新上述递归方法以实际存储结果并返回解决方案(如果已知)。如果我们看一下您的代码示例,我们可以对其进行修改以使其及时运行。

    int give(int a[],int x,int y,int age)
    {
        if(dp[x][y]!=-1) return dp[x][y];
        if(x==y) return age*a[x];

        int answer=max(age*a[x]+give(a,x+1,y,age+1),age*a[y]+give(a,x,y-1,age+1));

        dp[x][y]=answer;
        return answer;
    }

这只是一个片段,因为您需要修复边界条件并制作实际的全局dp数组,但是我希望这足以开始。