题目链接: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. spring boot学习02【如何在spring boot项目中访问jsp】

    1.配置application.properties文件 打开application.properties追加 spring.mvc.view.prefix=/WEB-ROOT/ spring.mvc ...

  2. 机器学习基础-Logistic回归2

    随机梯度上升法--一次仅用一个样本点来更新回归系数(因为可以在新样本到来时对分类器进行增量式更新,因而属于在线学习算法) 梯度上升法在每次更新回归系统时都需要遍历整个数据集,该方法在处理100个左右的 ...

  3. HDU 3763 CDs

    http://acm.hdu.edu.cn/showproblem.php?pid=3763 题意: 两组数据 看重复的有多少 如果每输入一个就去查找的话O(n^2) 会超时 所以可以用二法 第一组数 ...

  4. 【2018 Multi-University Training Contest 2】

    01: 02: 03: 04:https://www.cnblogs.com/myx12345/p/9394511.html 05: 06: 07:https://www.cnblogs.com/my ...

  5. linux下rename用法--批量重命名 转

    原文地址:https://www.cnblogs.com/hester/p/5615871.html Linux的rename 命令有两个版本,一个是C语言版本的,一个是Perl语言版本的,早期的Li ...

  6. springmvc和dubbo整合时,不配置spring listener报错找不到/WEB-INF/config/applicationContext.xml

    原因,dubbo2.6.3版本开始就需要先在listener中配置容器,否则报错,2.6.2版本则不需要

  7. 移动web页面字体大小三

    <script type="text/javascript"> (function (doc, win) { var docEl = doc.documentEleme ...

  8. TimePickerDialog

    package com.pingyijinren.helloworld.activity; import android.app.TimePickerDialog; import android.su ...

  9. PAT (Advanced Level) 1032. Sharing (25)

    简单题,不过数据中好像存在有环的链表...... #include<iostream> #include<cstring> #include<cmath> #inc ...

  10. POJ 3013 【需要一点点思维...】【乘法分配率】

    题意: (这题明显感觉自己是英语渣) 给n个点从1到n标号,下面一行是每个点的权,另外给出m条边,下面是每条边的信息,两个端点+权值,边是无向边.你的任务是选出一些边,使这个图变成一棵树.这棵树的花费 ...