张迪的私人酒庄里有一批窖藏美酒,张迪准备每天开一桶请同事们下班嗨皮
(1)这些酒桶被编号为1~n,每一天张迪可以在最前面的酒桶或者最后面的酒桶中搬出一桶打开;
(2)每一桶酒i都有一个初始售价p(i),这些酒放得越久,窖龄越大,价值越高;
(3)放了a天后,窖龄为a,美酒价值为p(i)*a。
给定每一桶酒的初始价值p(i),第一天开启的美酒的窖龄为1,此后每增加一天美酒的窖龄就增加1,请求出张迪请客最多会喝掉多少价值的美酒。
解答要求时间限制:1000ms, 内存限制:256MB
输入
第1行:整数n(1<= n <= 2000);
第i+l行:编号为i的美酒的初始价值p(i) (0 <= p(i) <= 1000)。
输出
1行:张迪请客喝掉的最大价值。
样例
输入样例 1 复制
5 1 3 1 5 2
输出样例 1
43
提示样例 1
张迪喝掉这些美酒(初始价值1,3,1,5,2)的顺序为:第一天喝掉第1桶,第二天喝掉第5桶,第三天喝掉第2桶,第四天喝掉第3桶,第5天喝掉第4桶,喝掉的最大价值为 1×1+2×2+3×3+4×1+5×5=43。
思路:沿对角线进行状态变换的动态规划
#include <stdio.h>
#include <string.h>
// max(i,j) = sum(i,j) + max { max(i+1,j), max(i,j-1) }
int max(int a,int b) {
return a > b ? a:b;
}
void calcSum(int *sum,int *p,int n) {
for(int k = 0;k<n;k++) {
if (k==0) {
sum[k]=p[k];
continue;
}
sum[k]=sum[k-1]+p[k];
}
}
//int dfs(int left, int right, int *p, int *sum) {
// if(left == right) {
// return p[left];
// }
// return (sum[right]-sum[left]+p[left]) + max(dfs(left+1,right,p,sum),dfs(left,right-1,p,sum));
//}
int getMaxValue(int *p,int n) {
int sum[n];
calcSum(sum,p,n);
int f[n+1][n+1];
memset(f,0,sizeof(f));
for (int i=1;i<=n;i++) {
f[i][i]=p[i-1];
}
for (int len=n-1;len>=0;len--){
int j = n-len+1;
for (int i =1;i<=len;i++,j++) {
f[i][j]=max(f[i][j-1],f[i+1][j]) + (sum[j-1]-sum[i-1]+p[i-1]);
}
}
return f[1][n];
}
int main() {
int n;
scanf("%d",&n);
// printf("n is:%d.\n",n);
int p[n];
for (int i = 0; i<n; i++) {
scanf("%d",&p[i]);
}
int res = getMaxValue(p,n);
printf("%d",res);
return 0;
}