【动态规划、dp】P2858 [USACO06FEB] Treats for the Cows G/S 题解

题意

约翰经常给产奶量高的奶牛发特殊津贴,于是很快奶牛们拥有了大笔不知该怎么花的钱。为此,约翰购置了 N ( 1 ≤ N ≤ 2000 ) N(1≤N≤2000) N(1N2000) 份美味的零食来卖给奶牛们。每天约翰售出一份零食。当然约翰希望这些零食全部售出后能得到最大的收益,这些零食有以下这些有趣的特性:

零食按照 1 , … , N 1,…,N 1,,N 编号,它们被排成一列放在一个很长的盒子里。盒子的两端都有开口,约翰每天可以从盒子的任一端取出最外面的一个。
与美酒与好吃的奶酪相似,这些零食储存得越久就越好吃。当然,这样约翰就可以把它们卖出更高的价钱。
每份零食的初始价值不一定相同。约翰进货时,第i份零食的初始价值为 V i ( 1 ≤ V ≤ 1000 ) V_i(1≤V≤1000) Vi(1V1000)
第i份零食如果在被买进后的第 a a a 天出售,则它的售价是 V i × a V_i ×a Vi×a V i V_i Vi
表示的是从盒子顶端往下的第i份零食的初始价值。约翰告诉了你所有零食的初始价值,并希望你能帮他计算一下,在这些零食全被卖出后,他最多能得到多少钱。

思路

考虑动态规划,记 d p i , j dp_{i,j} dpi,j 表示前 i i i次操作中 j j j 次从顶端拿走 j j j 次最多赚到的钱,则因为每次可以从顶部和底部拿:

d p i , j = max ⁡ ( d p i − 1 , j + a n − ( i − j ) + 1 × i , d p i − 1 , j − 1 + a i × i ) dp_{i,j} = \max(dp_{i - 1,j} + a_{n-(i -j)+1} \times i,dp_{i-1,j-1} + a_i \times i) dpi,j=max(dpi1,j+an(ij)+1×i,dpi1,j1+ai×i)

其中 d p i − 1 , j + a n − ( i − j ) + 1 × i dp_{i - 1,j} + a_{n-(i -j)+1} \times i dpi1,j+an(ij)+1×i 表示从底部拿,因为这是第 i − j i - j ij 次从底部拿,则拿的是从上往下数第 n − ( i − j ) + 1 n-(i-j)+1 n(ij)+1 个, d p i − 1 , j − 1 + a i × i dp_{i-1,j-1} + a_i \times i dpi1,j1+ai×i 同理。

注意 d p i , 0 = d p i − 1 , 0 + a n − i + 1 × i , d p i , i = d p i − 1 , i − 1 + a i × i dp_{i,0} = dp_{i-1,0}+a_{n-i+1} \times i,dp_{i,i} = dp_{i-1,i-1} + a_i \times i dpi,0=dpi1,0+ani+1×i,dpi,i=dpi1,i1+ai×i
在这里插入图片描述

代码

#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,a[2005];
int dp[2005][2005],ans = -1e18; 
signed main() {
	scanf("%lld",&n);
	for(int i = 1;i <= n;i++) scanf("%lld",&a[i]);
	for(int i = 1;i <= n;i++) {
		dp[i][0] = dp[i - 1][0] + a[n - i + 1] * i;
		dp[i][i] = dp[i - 1][i - 1] + a[i] * i;
		for(int j = 1;j < i;j++) {
			dp[i][j] = max(dp[i - 1][j] + a[n - (i - j) + 1] * i,dp[i - 1][j - 1] + a[j] * i);
		}
	}
	for(int i = 0;i <= n;i++) ans = max(ans,dp[n][i]);
	printf("%lld\n",ans);
    return 0;
}
  • 35
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值