题意: 给出n个数字a(i),每次你可以取出最左边的数字或者取出最右边的数字,一共取n次取完。假设你第i次取的数字是x,那么你可以获得i*x的价值。现在你需要规划取数顺序,使得总价值和最大。
思路: dp[k][i]dp[k][i]表示第kk次取,左边取到了位置的最大值,那么右边也就取到j=n−(k−i)j=n−(k−i)。
dp[k][i]dp[k][i]可以由两种状态转移过来:
①上一次取了最左边,dp[k−1][i−1]+a[i−1]∗(k−1),(1≤i≤k)dp[k−1][i−1]+a[i−1]∗(k−1),(1≤i≤k)
②上一次取了最右边,dp[k−1][i]+a[j+1]∗(k−1),(1≤i≤k)dp[k−1][i]+a[j+1]∗(k−1),(1≤i≤k)
所以:dp[k][i]=max(dp[k−1][i−1]+a[i−1]∗(k−1),dp[k−1][i]+a[j+1]∗(k−1)),(1≤i≤k)dp[k][i]=max(dp[k−1][i−1]+a[i−1]∗(k−1),dp[k−1][i]+a[j+1]∗(k−1)),(1≤i≤k)
//#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int MAXN = 2005;
int n, a[MAXN], dp[MAXN][MAXN];
int main()
{
scanf("%d", &n);
for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
int MAX = 0;
for (int k = 1; k <= n+1; k++)
{
for (int i = 1; i <= k; i++)
{
int j = n-(k-i);
dp[k][i] = max(dp[k-1][i-1]+a[i-1]*(k-1), dp[k-1][i]+a[j+1]*(k-1));
MAX = max(MAX, dp[k][i]);
}
}
printf("%d\n", MAX);
return 0;
}
/*
5
1 3 1 5 2
*/