首页 > 代码库 > 区间DP Treats for the Cows POJ - 3186

区间DP Treats for the Cows POJ - 3186

题意:给长度为n的序列,每次只能从首或尾取一个数,第i次取的数权值为(数值*i),求取完所有的数可以达到的最大权值。

网上都说是简单dp,自己想了很久都没想明白。。。

从后面推前面,由小区间推大区间。dp[i][j]代表要取的区间[i,j] ,区间长度为n的序列,从区间长度为1开始推,dp[i][i]=n*a[i]表示最后一个取走的数是i;

当区间长度为2时 dp[i][i+1]=max(dp[i][i]+a[i+1]*(n-1),dp[i+1][i+1]+a[i]*(n-1)) 表示从(最后取走的数是i,倒数第二取走的数是i+1),(最后取走的数是i+1,倒数第二取走的数是 i)中取最大值。

dp[i][j]=max(dp[i+1][j]+a[i]*(n-j+i),dp[i][j-1]+a[j]*(n-j+i));

想清楚后还是蛮简单的。。

技术分享
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#define maxn 2005
using namespace std;
int a[maxn],dp[maxn][maxn];
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        dp[i][i]=n*a[i];
    }
    for(int l=2;l<=n;l++)
    {
        for(int i=1;i<=n-l+1;i++)
        {
            int j=i+l-1;
            dp[i][j]=max(dp[i+1][j]+a[i]*(n-l+1),dp[i][j-1]+a[j]*(n-l+1));
        }
    }
    printf("%d\n",dp[1][n]);
    return 0;
}
View Code

 

区间DP Treats for the Cows POJ - 3186