题目描述
有 �N 个不同的正整数 �1x1, �2x2, ..., ��xN 排成一排,我们可以从左边或右边去掉连续的 �i (1≤�≤�)(1≤i≤n) 个数(只能从两边删除数),剩下 �−�N−i 个数,再把剩下的数按以上操作处理,直到所有的数都被删除为止。
每次操作都有一个操作价值,比如现在要删除从 �i 位置到 �k 位置上的所有的数。操作价值为 ∣��−��∣×(�−�+1)∣xi−xk∣×(k−i+1) ,如果只去掉一个数,操作价值为这个数的值。 问如何操作可以得到最大值,求操作的最大价值。
输入格式
第一行为一个正整数 �N ;
第二行有 �N 个用空格隔开的 �N 个不同的正整数。
输出格式
一行,包含一个正整数,为操作的最大值
输入输出样例
输入 #1
6 54 29 196 21 133 118
输出 #1
768
该题目是一道动态规划的题目:
1.定义状态:
f[i][j]表示从i开始删除j个数的最大价值
2.写出状态转移方程:
我们将i到j中的一段序列分为左右两段,再将右端序列进行分解,
对于f[i][j]=j*abs(a[i]-a[j])
对于处于i到j中间的分割点进行循环分割,并取最大值
for(int k=1;k<j;k++) //分开删
f[i][j]=max(f[i][j],f[i][k]+f[k+i][j-k]);
}
3.根据状态转移方程式找出递推顺序:
很显然,我们要求的是f[1][n],
递推顺序为顺推
(此处希望大佬指点)
4.处理递推的边界:
显然,如果只删除一个数,其最大价值就是该数的值
for(int i=1;i<=n;i++)
{
cin>>a[i];
f[i][1]=a[i];
}
5.找出结果:
其实我们在第散布是已经做好了,我们要求的就是从第1个数开始删除n个数的最大价值
很显然就是f[1][n]
下面展示代码:
#include<bits/stdc++.h>
using namespace std;
int n,ans,a[505],f[505][505]; //f[i][j]表示的是从i开始删除j个数得到的最大值
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
f[i][1]=a[i]; //显然,删除一个数的最大值是其本身
}
for(int j=2;j<=n;j++) //从i开始来删掉j个数
for(int i=1;i<=n-j+1;i++)
{
f[i][j]=j*abs(a[i]-a[i+j-1]); //直接删
for(int k=1;k<j;k++) //分开删
f[i][j]=max(f[i][j],f[i][k]+f[k+i][j-k]);
}
cout<<f[1][n];
return 0;
}
个人笔记,若大佬刷到可以多多指教!