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代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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) 编辑 收藏 举报