[USACO06FEB]奶牛零食Treats for the Cows (dp)

[USACO06FEB]奶牛零食Treats for the Cows

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

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

Hint
这是一道多倍经验题,一道dp入门题
原型是方格取数
考虑用dp[i][j]表示取i个零食,左边取了j个时的最大收益
那么右边了i-j个零食
可以想到$$dp[i][j]=max{dp[i-1][j]+v[n-(i-j)+1]*i,dp[i-1][j-1]+v[j]*n}$$
即考虑第j个零食取最左边还是取最右边

code

#include <cstdio>
#include <iostream>
#include <algorithm>
#define siz 2010
#define maxn(a,b) (a>b?a:b)
using namespace std;
int n, ans;
int a[siz], dp[siz][siz];
int main() {

    scanf("%d",&n);
    for(int i=1; i<=n; ++i) scanf("%d",&a[i]);
    for(int i=1; i<=n; ++i)
      for(int j=0; j<=i; ++j) {
        int r = i-j;
        dp[i][j] = max(dp[i-1][j]+a[n-r+1]*i,dp[i-1][j-1]+a[j]*i);
      }
    for(int i=0; i<=n; ++i) ans = maxn(dp[n][i],ans);
    printf("%d",ans);
    return 0;
}
posted @ 2018-07-12 15:15  Nepenthe  阅读(211)  评论(0)    收藏  举报


删边加边,浮生建模