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
答案 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数组,但是我希望这足以开始。