题意:给长度为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; }
时间: 2024-12-17 06:14:56