POJ 3186 Treats for the Cows

Treats for the Cows

Time Limit: 1000MS

 

Memory Limit: 65536K

Total Submissions: 7690

 

Accepted: 4074

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.

Input

Line 1: A single integer, N 

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

Output

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

Sample Input

5
1
3
1
5
2

Sample Output

43

Hint

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.

Source

USACO 2006 February Gold & Silver

算法分析:

题意:

在一个长度为n的区间里,你可以在两端(左端或者右端)取出一个数,这个数乘以他是第几次取出来的。求和的最大值。

分析:

dp[ i ][ j ]:表示在区间[ i , j ]j>=i 里可以获得的最大值。

如果我们从里往外进行计算,找一个数以它作为最后取出来的,由题意可以知道区间[ i , j ]只可能由区间 [ i+1,j ]或者 [ i , j-1 ] 组成,结合题意
 

状态转移方程:

dp[i][j]=max(dp[i+1][j]+a[i]*(n+i-j),dp[i][j-1]+a[j]*(n+i-j));

代码实现:

#include<cstdio>  
#include<cstring>  
#include<cstdlib>  
#include<cctype>  
#include<cmath>  
#include<iostream>  
#include<sstream>  
#include<iterator>  
#include<algorithm>  
#include<string>  
#include<vector>  
#include<set>  
#include<map>  
#include<stack>  
#include<deque>  
#include<queue>  
#include<list>  
using namespace std;  
const double eps = 1e-8;  
typedef long long LL;  
typedef unsigned long long ULL;  
const int INT_INF = 0x3f3f3f3f;  
const int INT_M_INF = 0x7f7f7f7f;  
const LL LL_INF = 0x3f3f3f3f3f3f3f3f;  
const LL LL_M_INF = 0x7f7f7f7f7f7f7f7f;  
const int dr[] = {0, 0, -1, 1, -1, -1, 1, 1};  
const int dc[] = {-1, 1, 0, 0, -1, 1, -1, 1}; 
const long long BASE = 1e18; 
const int MOD = 1e9 + 7;  
const double pi = acos(-1.0);  
const int MAXN = 1e5 + 10;  
const int MAXT = 10000 + 10;  
const int M=2005;
using namespace std;
int dp[M][M],a[M];
int main()
{
	int n;
    while(scanf("%d",&n)!=EOF)
    {
    	memset(a,0,sizeof(a));
    	memset(dp,0,sizeof(dp));
        for(int i=1;i<=n;i++)
        	scanf("%d",&a[i]);
		for(int i=n;i>=1;i--) //这里i逆序的原因:dp[i][j]由dp[i+1][j]得来的,按照题意,它是有后端取出的
		 for(int j=i;j<=n;j++) //j正序原因同上
		 dp[i][j]=max(dp[i+1][j]+a[i]*(n+i-j),dp[i][j-1]+a[j]*(n+i-j));
		printf("%d\n",dp[1][n]);
    }
 
    return 0;
}

猜你喜欢

转载自blog.csdn.net/sdz20172133/article/details/81212091