【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 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.