题目描述
有 N 个不同的正整数 x1, x2, ..., xN 排成一排,我们可以从左边或右边去掉连续的 i (1≤i≤n) 个数(只能从两边删除数),剩下 N−i 个数,再把剩下的数按以上操作处理,直到所有的数都被删除为止。
每次操作都有一个操作价值,比如现在要删除从 i 位置到 k 位置上的所有的数。操作价值为 ∣xi−xk∣×(k−i+1) ,如果只去掉一个数,操作价值为这个数的值。 问如何操作可以得到最大值,求操作的最大价值。
输入格式
第一行为一个正整数 N ;
第二行有 N 个用空格隔开的 N 个不同的正整数。
输出格式
一行,包含一个正整数,为操作的最大值
输入样例
6
54 29 196 21 133 118
输出样例
768
说明/提示
【样例解释和说明】
说明,经过 3 次操作可以得到最大值,第一次去掉前面 3 个数:54 、29 、196 ,操作价值为 426。第二次操作是在剩下的三个数 (21,133,118) 中去掉最后一个数118,操作价值为 118。第三次操作去掉剩下的 2 个数:21 和 133 ,操作价值为 224。操作总价值为 426+118+224=768 。
【数据范围】
3≤N≤100 ,1≤xi≤1000
解析:
N<100,n^2可以通过。
通过题目看出只能从两边删除,假设1,2,3,4 这四个数,随便删假设删除前两个1 2,最后一个4,第三个3, 如果这种情况最大。一直从前删除也有相同的结果。1 2,3,4 这样结果相同。
所以利用动态规划,从前往后删除。
设dp[i]表示删除前i个最大值。然后枚举1-i,2-i,3-i……i-i每种情况的最大值。
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const ll MAX = 1e3;
const ll M = 1e9 + 7;
ll a[MAX];
ll dp[MAX];
ll val(ll l, ll r)
{
if (l == r)
{
return a[l];
}
return abs(a[l] - a[r]) * (r - l + 1);
}
int main()
{
ll n;
cin >> n;
for (int i = 1; i <= n; i++)
{
cin >> a[i];
}
dp[1] = a[1];
for (int i = 2; i <= n; i++)
{
dp[i] = a[i];
for (int j = 1; j <= i; j++)
{
dp[i] = max(dp[i], dp[j-1] + val(j, i));
}
}
cout << dp[n] << endl;
return 0;
}