题目链接:http://poj.org/problem?id=3186

Treats for the Cows
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 6548   Accepted: 3446

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

 
 
 
一.正向思维:
1.dp[l][r]表示:左边取了l个, 右边取了r个的最大值。
2.枚举左边取了多少个, 再枚举右边取了多少个。
3.对于当前的 dp[l][r],它可以是在dp[l-1][r]的基础上取了a[l];也可以是在dp[l][r-1]的基础上取了a[n+1-r]。所以:
dp[l][r] = max(dp[l-1][r]+a[l], dp[l][r-1]+a[n+1-r])

当然,还需要注意边界条件:l-1>=0,r-1>=0

 
代码如下:
 #include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <string>
#include <set>
#define ms(a,b) memset((a),(b),sizeof((a)))
using namespace std;
typedef long long LL;
const double EPS = 1e-;
const int INF = 2e9;
const LL LNF = 2e18;
const int MAXN = 2e3+; int n;
int a[MAXN], dp[MAXN][MAXN]; int main()
{
while(scanf("%d", &n)!=EOF)
{
for(int i = ; i<=n; i++)
scanf("%d", &a[i]); memset(dp, , sizeof(dp));
for(int l = ; l<=n; l++)
for(int r = ; l+r<=n; r++)
{
if(l!=) dp[l][r] = max(dp[l-][r]+(l+r)*a[l], dp[l][r]);
if(r!=) dp[l][r] = max(dp[l][r], dp[l][r-]+(l+r)*a[n+-r]);
} int ans = -INF;
for(int l = ; l<=n; l++)
ans = max(ans, dp[l][n-l]);
printf("%d\n", ans);
}
}
 
二.逆向思维:
1.逆向推导, 即把过程逆过来,然后就变成了:从中间开始往外取,这样就变成了连续的一段。
2.dp[i][j]表示:区间[i, j]的最大值。
3.枚举区间长度, 然后再枚举起点(终点就确定了)。对于dp[i][j],它可以是在dp[i+1][j]的基础上取了a[i],也可以是在dp[i][j-1]的基础上取了a[j]。两者取其大。
 
 
代码如下:
 #include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <string>
#include <set>
#define ms(a,b) memset((a),(b),sizeof((a)))
using namespace std;
typedef long long LL;
const double EPS = 1e-;
const int INF = 2e9;
const LL LNF = 2e18;
const int MAXN = 2e3+; int n;
int a[MAXN], dp[MAXN][MAXN]; int main()
{
while(scanf("%d", &n)!=EOF)
{
for(int i = ; i<=n; i++)
scanf("%d", &a[i]); for(int i = ; i<=n; i++)
dp[i][i] = a[i]*n; for(int len = ; len<=n; len++)
for(int i = ; i+len-<=n; i++)
{
int j = i+len-;
dp[i][j] = max(dp[i+][j]+(n-len+)*a[i], dp[i][j-]+(n-len+)*a[j]);
} printf("%d\n", dp[][n]);
}
}

三.记忆化搜索:

1.上面的两种方法都要考虑枚举顺序的问题,有时比较不好处理。那么可以用记忆化搜索。

2. 思维与方法二一样,只是写法不同。

代码如下:

 #include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <string>
#include <set>
#define ms(a,b) memset((a),(b),sizeof((a)))
using namespace std;
typedef long long LL;
const double EPS = 1e-;
const int INF = 2e9;
const LL LNF = 2e18;
const int MAXN = 2e3+; int n;
int a[MAXN], dp[MAXN][MAXN]; int dfs(int l, int r)
{
if(l==r) return n*a[l];
if(dp[l][r]!=-) return dp[l][r];
int k = n-r+l; dp[l][r] = max(k*a[l]+dfs(l+, r), k*a[r]+dfs(l,r-));
return dp[l][r];
} int main()
{
while(scanf("%d", &n)!=EOF)
{
for(int i = ; i<=n; i++)
scanf("%d", &a[i]); memset(dp, -, sizeof(dp));
printf("%d\n", dfs(,n));
}
}

POJ3186 Treats for the Cows —— DP的更多相关文章

  1. kuangbin专题十二 POJ3186 Treats for the Cows (区间dp)

    Treats for the Cows Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 7949   Accepted: 42 ...

  2. poj3186 Treats for the Cows

    http://poj.org/problem?id=3186 Treats for the Cows Time Limit: 1000MS   Memory Limit: 65536K Total S ...

  3. BZOJ 1652: [Usaco2006 Feb]Treats for the Cows( dp )

    dp( L , R ) = max( dp( L + 1 , R ) + V_L * ( n - R + L ) , dp( L , R - 1 ) + V_R * ( n - R + L ) ) 边 ...

  4. poj 3186 Treats for the Cows(dp)

    Description FJ has purchased N (1 <= N <= 2000) yummy treats for the cows who get money for gi ...

  5. poj3186 Treats for the Cows(区间)

    题目链接:http://poj.org/problem?id=3186 题意:第一个数是N,接下来N个数,每次只能从队列的首或者尾取出元素. ans=每次取出的值*出列的序号.求ans的最大值. 样例 ...

  6. POJ3186:Treats for the Cows(区间DP)

    Description FJ has purchased N (1 <= N <= 2000) yummy treats for the cows who get money for gi ...

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

    Treats for the Cows 先搬中文 Descriptions: 给你n个数字v(1),v(2),...,v(n-1),v(n),每次你可以取出最左端的数字或者取出最右端的数字,一共取n次 ...

  8. poj 3186 Treats for the Cows(区间dp)

    Description FJ has purchased N (1 <= N <= 2000) yummy treats for the cows who get money for gi ...

  9. (区间dp + 记忆化搜索)Treats for the Cows (POJ 3186)

    http://poj.org/problem?id=3186   Description FJ has purchased N (1 <= N <= 2000) yummy treats ...

随机推荐

  1. [luoguP2577] [ZJOI2005]午餐(DP)

    传送门 显然吃饭时间越长的人排在前面越好,所以先排序. f[i][j]表示前i个人,A队的打饭时间为j的最优解,每个人只有两种选择,去A队或是去B队. #include <cstdio> ...

  2. POJ3321Apple Tree【dfs 树状数组】

    题目大意:一棵树(不一定是二叉树!!),树的节点上本来都有一个苹果,要求完成以下操作: 1.指定某个节点,如果这个节点原本有苹果则拿去,如果没有苹果则填上一个苹果 2.询问某个节点以及其子树一共有多少 ...

  3. cp: omitting directory解决方案

    cp: omitting directory是因为目录下面还有目录.应该使用递归方法.需要加入-r参数. 及:cp -r 该目录名.

  4. js命名

    JS变量名前加 _ 与 $ 的区别: 下划线一般当做私有属性, 业界会比较常用$开头作为框架.库的关键词前缀,目的是避免命名冲突

  5. HDU3430 (置换群循环节+中国剩余定理)

    题意:给出n张牌,标号为1-n,然后给出两个序列,序列1表示序列1,2,3,4……,n洗一次牌后到达的,序列2表示目标序列,问初始序列按序列1的洗牌方式洗几次能到达序列2的情况,如果不能到达输出-1. ...

  6. CDN是什么与CDN加速的原理

    CDN是什么 CDN全称:Content Delivery Network或Content Ddistribute Network,即内容分发网络 CDN设计思路 避让:尽可能避开互联网上有可能影响数 ...

  7. java基础 4 继承(1)抽象类与接口的区别

    抽象类: 是用来捕捉子类的通用特性的,至少包含一个抽象方法,该抽象方法必须在子类中实现,由于抽象类没有抽象方法的具体实现,因此不能对抽象类进行实例化. 接口: 定义了一组方法,是抽象方法的集合,但是接 ...

  8. eclipse bug之'<>'operator is not allowed for source level below 1.7

    eclipse中导入工程,报这个错'<>'operator is not allowed for source level below 1.7,把jdk改成1.7后,提示Android r ...

  9. How do you check if a variable is an array in JavaScript? [duplicate]

    https://stackoverflow.com/questions/767486/how-do-you-check-if-a-variable-is-an-array-in-javascript ...

  10. linux上安装启动elasticsearch-5.5.1完整步骤

    linux上安装启动elasticsearch-5.5.1完整步骤 学习了:https://blog.csdn.net/hingcheung/article/details/77144574 http ...