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 Input
5
1
3
1
5
2
Sample Output
43
Hint
按照这种下标顺序取数: 1, 5, 2, 3, 4
取出的数按顺序为:1, 2, 3, 1, 5
最大总价值和:1x1 + 2x2 + 3x3 + 4x1 + 5x5 = 43.
题目链接:https://vjudge.net/problem/POJ-3186
区间dp
dp[i][j] 代表从i取到j的最大总数
dp[i][j] = max(dp[i+1][j]+a[i]*(n+i-j) , dp[i][j-1]+a[j]*(n+i-j)) 即取右边的数 取左边的数 比较哪个大
AC代码
#include <iostream>
#include <cstdio>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <deque>
#include <vector>
#include <queue>
#include <string>
#include <cstring>
#include <map>
#include <stack>
#include <set>
#define Mod 1000000007
#define eps 1e-6
#define ll long long
#define INF 0x3f3f3f3f
#define MEM(x, y) memset(x, y, sizeof(x))
#define Maxn 2000+10
using namespace std;
int n;
int dp[Maxn][Maxn],a[Maxn];
int main()
{
MEM(dp,0);
MEM(a,0);
cin>>n;
for(int i=0;i<n;i++)
cin>>a[i];
for(int len=0;len<n;len++)//区间长度len
{
for(int i=0;i+len<n;i++)//固定区间左边起点
{
int l=i,r=i+len;//区间左、右点
//取右边的数 取左边的数 比较哪个大
dp[l][r]=max(dp[l+1][r]+a[l]*(n+l-r),dp[l][r-1]+a[r]*(n+l-r));
}
}
cout<<dp[0][n-1]<<endl;
return 0;
}
给你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 Input
5
1
3
1
5
2
Sample Output
43
Hint按照这种下标顺序取数: 1, 5, 2, 3, 4
取出的数按顺序为:1, 2, 3, 1, 5
最大总价值和:1x1 + 2x2 + 3x3 + 4x1 + 5x5 = 43.