大意:
给出n个数,将这个数列修改为不增序列或者不减序列,需要的最小代价是多少(每次修改的代价为修改前后的差的绝对值)
思路:
贪心的想法是每次修改必然修改到原数列中存在的数,因为不这样修改必然会修改多了。
然后先考虑修改到不减序列,那么可以先将a数组排序,得到b数组,然后(dp[i][j])代表将第i个数修改到(b[j])的代价最小值,那么这个最小值可以从(min(dp[i-1][1....j]))转移过来,但是这样复杂度很高,是(O(n^3))的,怎么优化呢,注意到每次更新j时也会更新(min(dp[i-1][1....j])),所以直接在更新(dp[i][j])的时候更新(min(dp[i][1....j]))即可,
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <cstdio>
#include <iostream>
#include <queue>
#include <stack>
#include <vector>
using namespace std;
const int N = 2e3 + 5;
typedef long long LL;
int n, a[N], b[N], dp[N][N];
int main() {
cin >> n;
for (int i = 0; i < n; i++) {
cin >> a[i];
b[i] = a[i];
}
sort(b, b + n);
for (int i = 0; i < n; i++) dp[0][i] = min(dp[0][i], abs(a[0] - b[i]));
for (int i = 1; i < n; i++) {
int temp = dp[i - 1][0];
for (int j = 0; j < n; j++) {
temp = min(temp, dp[i - 1][j]);
dp[i][j] = temp + abs(a[i] - b[j]);
}
}
int res = dp[n - 1][0];
for (int i = 0; i < n; i++) {
res = min(res, dp[n - 1][i]);
}
cout << res << endl;
}