Treats for the Cows POJ 3186

题意:给你一串有序的数,从第一天开始每天只能从这串数的两端之一取一个数,并且你得到的价值是这个数乘以你取该数的天数。

 

题解:DP。状态转移方程:dp[i][j]=max(dp[i+1][j]+v[i]*(n-(j-i)),dp[i][j-1]+v[j]*(n-(j-i)));

这里dp[i][j]的意思是倒数第n-j+i次在剩下的未被取出的i~j区间内取一个数所能获得的最大价值。即第n-j+i次在i~j区间内要么取i要么取j。如果取i则dp[i][j]=dp[i+1][j]+v[i]*(n-(j-1)),否则dp[i][j]=dp[i][j-1]+v[j]*(n-(j-i))。显然dp[i][j]要去两者的最大值,所以dp[i][j]=max(dp[i+1][j]+v[i]*(n-(j-i)),dp[i][j-1]+v[j]*(n-(j-i)))。那么倒数第一次所取得的最大价值dp[1][n]即为所求。

 

AC代码:

 

View Code
 1 #include<cstdio>
 2 #include<cmath>
 3 #include<cstring>
 4 #include<iostream>
 5 #include<algorithm>
 6 using namespace std;
 7 const int maxN=2005;
 8 int v[maxN],dp[maxN][maxN];
 9 int n;
10 int solve(){
11     memset(dp,0,sizeof(dp));
12     for(int i=n;i>=1;i--)
13         for(int j=i;j<=n;j++)
14             dp[i][j]=max(dp[i+1][j]+v[i]*(n-j+i),dp[i][j-1]+v[j]*(n-j+i));
15     return dp[1][n];
16 }
17 int main()
18 {
19     while(scanf("%d",&n)!=EOF){
20         for(int i=1;i<=n;i++)
21             scanf("%d",&v[i]);
22         printf("%d\n",solve());
23     }
24     return 0;
25 }

 

posted on 2012-09-24 17:42  Acmer_Roney  阅读(272)  评论(0编辑  收藏  举报

导航