[BZOJ 1652][USACO 06FEB]Treats for the Cows 題解(區間DP)

[BZOJ 1652][USACO 06FEB]Treats for the Cows

Description

FJ has purchased N (1 <= N <= 2000) yummy treats for the cows who get money for giving vast amounts of milk. FJ sells one treat per day and wants to maximize the money he receives over a given period time. The treats are interesting for many reasons: * The treats are numbered 1..N and stored sequentially in single file in a long box that is open at both ends. On any day, FJ can retrieve one treat from either end of his stash of treats. * Like fine wines and delicious cheeses, the treats improve with age and command greater prices. * The treats are not uniform: some are better and have higher intrinsic value. Treat i has value v(i) (1 <= v(i) <= 1000). * Cows pay more for treats that have aged longer: a cow will pay v(i)*a for a treat of age a. Given the values v(i) of each of the treats lined up in order of the index i in their box, what is the greatest value FJ can receive for them if he orders their sale optimally? The first treat is sold on day 1 and has age a=1. Each subsequent day increases the age by 1.html

約翰常常給產奶量高的奶牛發特殊津貼,因而很快奶牛們擁有了大筆不知該怎麼花的錢.爲此,約翰購置了N(1≤N≤2000)份美味的零食來賣給奶牛們.天天約翰售出一份零食.固然約翰但願這些零食所有售出後能獲得最大的收益.這些零食有如下這些有趣的特性:
•零食按照1..N編號,它們被排成一列放在一個很長的盒子裏.盒子的兩端都有開口,約翰每
天能夠從盒子的任一端取出最外面的一個.
•與美酒與好吃的奶酪類似,這些零食儲存得越久就越好吃.固然,這樣約翰就能夠把它們賣出更高的價錢.
•每份零食的初始價值不必定相同.約翰進貨時,第i份零食的初始價值爲Vi(1≤Vi≤1000).
•第i份零食若是在被買進後的第a天出售,則它的售價是vi×a.
Vi的是從盒子頂端往下的第i份零食的初始價值.約翰告訴了你全部零食的初始價值,並但願你能幫他計算一下,在這些零食全被賣出後,他最多能獲得多少錢.ios

Input
Line 1: A single integer,N
Lines 2..N+1: Line i+1 contains the value of treat v(i)git

Output
Line 1: The maximum revenue FJ can achieve by selling the treatsspa

Solution

1.初始化rest

f[i][i]表明這個只有這個物品賣出的利潤,顯然此時f[i][i]=v[i],同時記錄v[i]的前綴和,用於轉移。code

2.DPorm

方程爲f[l][r]=max(f[l+1][r],f[l][r-1])+v[r]-v[l-1],答案由兩種小1長度的區間獲得,加上區間和表明全部區間內的物品都延遲一天賣出。htm

Code

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#define R register
using namespace std;

int a[2010],v[2010],f[2010][2010];

inline int rd(){
    int x=0;
    bool f=1;
    char c=getchar();
    while(!isdigit(c)){
        if(c=='-') f=0;
        c=getchar();
    }
    while(isdigit(c)){
        x=(x<<1)+(x<<3)+(c^48);
        c=getchar();
    }
    return f?x:-x;
}

int main(){
    int n=rd();
    for(R int i=1;i<=n;++i){
        a[i]=f[i][i]=rd();
        v[i]=v[i-1]+a[i];
    }
    for(R int len=2;len<=n;++len)
        for(R int l=1;l<=n-len+1;++l){
            int r=l+len-1;
            f[l][r]=max(f[l+1][r],f[l][r-1])+v[r]-v[l-1]; 
        }
    printf("%d",f[1][n]);
    return 0;
}

有關區間DP的其餘講解參考個人隨筆:http://www.cnblogs.com/COLIN-LIGHTNING/p/9038198.htmlblog

相關文章
相關標籤/搜索