POJ 3186 Treats for the Cows (简单区间DP)

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.

题意:

   第n次从序列的头部或者尾部取一个数a[i],求n*a[i]累加和。

题解:

  很容易想到贪心地前面选取尽量小的数,但是仔细考虑是不行的。前面的选择会对后面的选择产生影响,这时就应该想到DP了。这类问题属于区间DP。假设dp[i][j]是区间[i,j]上的最大值,那么区间dp[i][j]可以由dp[i+1][j]选取a[i]或者dp[i][j-1]选取a[j]得到。但是我们直接dp是不好做的,需要从区间长度入手。具体实现请看代码。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int a[2005];
int dp[2005][2005];
int main()
{
    int n;
    while(cin>>n)
    {
        for(int i=1;i<=n;i++)
            cin>>a[i],dp[i][i]=a[i]*n;//区间长度为1的时候,当然是最后一个取。
        for(int len=1;len<n;len++)//枚举区间长度
            for(int i=1;i+len<=n;i++)//枚举区间的起点
            {
                int j=i+len;//区间的终点
                dp[i][j]=max(dp[i+1][j]+(n-len)*a[i],dp[i][j-1]+(n-len)*a[j]);
            }
        cout<<dp[1][n]<<endl;//答案就是1到n这个区间的最大值
    }
    return 0;
}
时间: 2024-08-24 06:12:01

POJ 3186 Treats for the Cows (简单区间DP)的相关文章

poj 3186 Treats for the Cows(区间dp)

Treats for the Cows Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 4375   Accepted: 2226 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 da

POJ - 3186 Treats for the Cows (区间DP)

题目链接:http://poj.org/problem?id=3186 题意:给定一组序列,取n次,每次可以取序列最前面的数或最后面的数,第n次出来就乘n,然后求和的最大值. 题解:用dp[i][j]表示i~j区间和的最大值,然后根据这个状态可以从删前和删后转移过来,推出状态转移方程: dp[i][j]=max(dp[i+1][j]+value[i]*k,dp[i][j-1]+value[j]*k) 1 #include <iostream> 2 #include <algorithm&

poj 3186 Treats for the Cows dp

#include <cstdio> #include <algorithm> using namespace std; #define maxn 2100 int dp[maxn][maxn]; int val[maxn]; int n; int main() { while(scanf("%d",&n)!=EOF) { int i,j; for(i=1;i<=n;i++) { scanf("%d",&val[i]);

【POJ - 3186】Treats for the Cows (区间dp)

Treats for the Cows 先搬中文 Descriptions: 给你n个数字v(1),v(2),...,v(n-1),v(n),每次你可以取出最左端的数字或者取出最右端的数字,一共取n次取完.假设你第i次取的数字是x,你可以获得i*x的价值.你需要规划取数顺序,使获得的总价值之和最大. Input 第一行一个数字n(1<=n<=2000). 下面n行每行一个数字v(i).(1<=v(i)<=1000) Output 输出一个数字,表示最大总价值和. Sample In

POJ 3186 Treats for the Cows

一开始想到的是,用一个标志位记录取第i个数的时间,但后来发现这个方法不行,可能性太多,没办法推 然后就看了解题报告的思路,说是用区间dp,状态是设出来了,但受固有思维影响,老想着怎么顺着推. 最后实在想不出了,看了代码,才发现要逆着推,从结束状态开始推起,这样公式就出来了 为了保证每一层循环要用到的值都已经被计算出来了,按区间长度进行枚举 纪念第一个区间dp吧 /* dp[i][j]:剩下第i个至第j个物品时,取掉剩下的所有物品能获得的最大值 dp[i][j]=max(dp[i+1][j]+v[

poj-3816 Treats for the Cows 【区间DP】

Treats for the Cows Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 4259   Accepted: 2150 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 da

POJ 3189 Treats for the Cows(两种DP方法解决)

Treats for the Cows Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 4264   Accepted: 2155 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 da

POJ 3186 Treats for the Cows 一个简单DP

DP[i][j]表示现在开头是i物品,结尾是j物品的最大值,最后扫一遍dp[1][1]-dp[n][n]就可得到答案了 稍微想一下,就可以, #include<iostream> #include<cstdio> #include<cstdlib> #include<cmath> #include<algorithm> #include<cstring> #include<cstring> #include<vect

poj 3186 Treats for the Cows (区间dp)

题意:给你一个序列,每次只能从头或为取数,然后乘以这是第几个数,最后加和,是加和最大 思路:假设长度最开始是1,然后依次枚举长度,以及起点,dp[i][j]是又里面的两端点扩出来的(ps:代码不是这么写的) 代码: #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn=2007; int a[maxn],dp[maxn][maxn]; i