題意:給出的一系列的數字,可以看成一個雙向隊列,每次只能從隊首或者隊尾出隊,第i個出隊就拿這個數乘以i,最後將和加起來,求最大和
由裏向外推,dp[i][j],表示從隊首取了前i個,從隊尾取了後j個,枚舉i,j
狀態轉移方程dp[i][j]=max(dp[i-1][j]+v[i]*(i+j),d[i][j-1]+v[n-j+1]*(i+j));
#include <stdio.h>
#include <iostream>
#include <string.h>
using namespace std;
const int N=3001;
int dp[N][N];
int n,v[N];
int MAX(int x,int y)
{
if(x>y)
return x;
return y;
}
int main()
{
while(scanf("%d",&n)!=EOF)
{
memset(dp,0,sizeof(dp));
for(int i=1;i<=n;i++)
{
scanf("%d",&v[i]);
dp[i][i]=n*v[i];
}
for(int len=2;len<=n;len++)
{
for(int i=1;i<=n-len+1;i++)
{
int j=i+len-1;
if(i+1<=j&&i+1<=n)
{
dp[i][j]=MAX(dp[i][j],dp[i+1][j]+(n-j+i)*v[i]);
}
if(j-1>=i)
{
dp[i][j]=MAX(dp[i][j],dp[i][j-1]+(n-j+i)*v[j]);
}
}
}
printf("%d\n",dp[1][n]);
}
}