P2858 [USACO06FEB]奶牛零食Treats for the Cows

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

•零食按照1..N编号,它们被排成一列放在一个很长的盒子里.盒子的两端都有开口,约翰每

天可以从盒子的任一端取出最外面的一个.

•与美酒与好吃的奶酪相似,这些零食储存得越久就越好吃.当然,这样约翰就可以把它们卖出更高的价钱.

•每份零食的初始价值不一定相同.约翰进货时,第i份零食的初始价值为Vi(1≤Vi≤1000).

•第i份零食如果在被买进后的第a天出售,则它的售价是vi×a.

Vi的是从盒子顶端往下的第i份零食的初始价值.约翰告诉了你所有零食的初始价值,并希望你能帮他计算一下,在这些零食全被卖出后,他最多能得到多少钱.

输入输出格式

输入格式:

 

Line 1: A single integer, N

Lines 2..N+1: Line i+1 contains the value of treat v(i)

 

输出格式:

 

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

 

输入输出样例

输入样例#1: 复制
5
1
3
1
5
2
输出样例#1: 复制
43

说明

Explanation of the sample:

Five treats. On the first day FJ can sell either treat #1 (value 1) or treat #5 (value 2).

FJ sells the treats (values 1, 3, 1, 5, 2) in the following order of indices: 1, 5, 2, 3, 4, making 1x1 + 2x2 + 3x3 + 4x1 + 5x5 = 43.

题意:

就是说有一堆零食按顺序放入一个圆筒里面,你每次只能从这个桶的两端拿东西,求最后把所有东西都拿出来之后最多能拿到多少钱

 

题解(很常规的区间dp)一、:

参考:https://www.luogu.org/blog/chtholly-willem/solution-p2858#

区间dp就是可以把一个大问题化成很多小问题,并且小问题可以转化为大问题从而求解

这个区间dp没有第三重for循环的原因是题目上说只能从圆筒的两端拿东西,那么我们的子问题需要的条件是在子问题这个长度下可以从两端拿东西,但是父问题的长度肯定比

子问题的长度要长,所以我们要先把子问题外的零食先卖掉

那么我们就要先把父问题转化为子问题,我们就可以把父区间的一个端点先比子零食卖出去,这样父问题就转化为子问题了

具体看代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<cstdlib>
 6 #include<iomanip>
 7 #include<algorithm>
 8 #include<fstream>
 9 using namespace std;
10 int dp[2005][2005],a[2005];
11 int main(){
12     int n,l,i,j;
13     cin>>n;
14     for(i=1;i<=n;i++){
15         cin>>a[i];
16         dp[i][i]=a[i]*n;//初始化:将区间长度为1的情况赋值为最后一个拿(n*a[i])
17     }
18     for(l=2;l<=n;l++){//枚举长度
19         for(i=1;(i+l-1)<=n;i++){//枚举开头点,注意范围(开头点加长度减一不超过总长度)
20             j=i+l-1;//推出结束点
21             dp[i][j]=max(dp[i+1][j]+a[i]*(n-l+1),dp[i][j-1]+a[j]*(n-l+1));//有两种情况一种是选开头点的那一个最优,一种是选结束点的那一个最优
22         }
23     }
24     cout<<dp[1][n]<<endl;//最后直接输出从开头到末尾的最大值
25     return 0;
26 }
View Code

 

 

题解二、:

参考:https://www.luogu.org/blog/fivehours/solution-p2858

代码:

 1 #include <cstdio>
 2 
 3 #define re register
 4 #define max(a,b) ((a)>(b)?(a):(b))
 5 #define min(a,b) ((a)<(b)?(a):(b))
 6 
 7 const int N = 2e3+10;
 8 
 9 int n;
10 int a[N];
11 int f[N][N];
12 int s[N];
13 
14 int dfs(int l,int r) {
15     if(f[l][r]) {
16         return f[l][r];
17     }
18     f[l][r]=max(dfs(l+1,r)+(s[r]-s[l])+a[l],dfs(l,r-1)+(s[r-1]-s[l-1])+a[r]);
19     return f[l][r];
20 }
21 
22 void Input() {
23     scanf("%d",&n);
24     for(re int i=1; i<=n; ++i) {
25         scanf("%d",&a[i]);
26         f[i][i]=a[i];
27         s[i]=s[i-1]+a[i];
28     } 
29 }
30 
31 void Solve() {
32     printf("%d",dfs(1,n)); 
33 }
34 
35 int main(void) {
36     Input();
37     Solve();
38     return 0;
39 }
View Code

 

 

 

posted @ 2019-06-24 11:08  kongbursi  阅读(221)  评论(0编辑  收藏  举报