【8月刷题打卡】删数

61 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第10天,点击查看活动详情

删数

题目描述

NN 个不同的正整数 x1x_1, x2x_2, ..., xNx_N 排成一排,我们可以从左边或右边去掉连续的 ii (1in)(1 \le i \le n) 个数(只能从两边删除数),剩下 NiN-i 个数,再把剩下的数按以上操作处理,直到所有的数都被删除为止。

每次操作都有一个操作价值,比如现在要删除从 ii 位置到 kk 位置上的所有的数。操作价值为 xixk×(ki+1)|x_i-x_k| \times (k-i+1) ,如果只去掉一个数,操作价值为这个数的值。 问如何操作可以得到最大值,求操作的最大价值。

输入格式

第一行为一个正整数 NN ;

第二行有 NN 个用空格隔开的 NN 个不同的正整数。

输出格式

一行,包含一个正整数,为操作的最大值

样例 #1

样例输入 #1

6
54 29 196 21 133 118

样例输出 #1

768

提示

【样例解释和说明】

说明,经过 33 次操作可以得到最大值,第一次去掉前面 33 个数:54542929196196 ,操作价值为 426426。第二次操作是在剩下的三个数 (21,133,118)(21,133,118) 中去掉最后一个数118118,操作价值为 118118。第三次操作去掉剩下的 22 个数:2121133133 ,操作价值为 224224。操作总价值为 426+118+224=768426+118+224=768

【数据范围】

3N1003≤N≤1001xi10001 \le x_i \le 1000

#include <cstdio>
#include <algorithm>
using namespace std;

int n, val[105], dp[105];

inline int Val(int l, int r) {
  return abs(val[l] - val[r]) * (r - l + 1);
}

int main(int argc, char const *argv[]) 
{
  // freopen("nanjolno.in", "r", stdin);
  // freopen("nanjolno.out", "w", stdout);
  
  scanf("%d", &n);
  for(int i = 1; i <= n; ++i) scanf("%d", &val[i]);
  for(int i = 1; i <= n; ++i) {
    dp[i] = max(dp[i], dp[i - 1] + val[i]);
    for(int j = 2; j <= i; ++j)
      dp[i] = max(dp[i], dp[i - j] + Val(i - j + 1, i));
  }
  printf("%d\n", dp[n]);

  // fclose(stdin), fclose(stdout);
  return 0;
}