AcWing273.分级
题目
给定长度为N的序列A,构造一个长度为N的序列B,满足:
1、B非严格单调,即B1≤B2≤…≤BN或B1≥B2≥…≥BN。
2、最小化 S=∑Ni=1|Ai−Bi|。
只需要求出这个最小值S。
输入格式
第一行包含一个整数N。
接下来N行,每行包含一个整数Ai。
输出格式
输出一个整数,表示最小S值。
数据范围
1≤N≤2000,
1≤|Ai|≤109
输入样例:
7
1
3
2
4
5
3
9
输出样例:
3
代码及思路如下
#include <bits/stdc++.h>
using namespace std;
/**
* dp[i][j]代表在i的长度下,以j为结尾的最小值
* dp[i][j] = min(dp[i - 2][z] + abs(arr[i] - j));///z <= j
* **/
const int MAXN = 2005;
typedef long long ll;
const ll inf = __LONG_LONG_MAX__;
ll arr[MAXN];
ll dp[MAXN][MAXN];
void Init(){
memset(arr, 0, sizeof(arr));
memset(dp, 0, sizeof(dp));
}
int n;
vector<ll>vec;
int main(){
scanf("%d", &n);
Init();
vec.clear();
for(int i = 1; i <= n; i ++){
scanf("%lld", &arr[i]);
vec.push_back(arr[i]);
}
sort(vec.begin(), vec.end());
for(int i = 1; i <= n; i ++){
ll temp = dp[i - 1][1];
for(int j = 1; j <= n; j ++){
temp = min(temp, dp[i - 1][j]);
dp[i][j] = temp + abs(arr[i] - vec[j - 1]);///vec从0开始
}
}
ll re = dp[n][1];
for(int i = 1; i <= n; i ++){
re = min(dp[n][i], re);
}
printf("%lld\n", re);
return 0;
}