题意
传送门 POJ 3666
基本思路是对 N 个位置枚举所有可能高度,并 dp 求最大值。可能高度取 N 个位置的高度即可,排序以方便顺序 dp。对于升序的情况
复杂度为 ,递推式可以优化为
实现上复用数组,降序情况同理。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <queue>
#define min(a,b) (((a) < (b)) ? (a) : (b))
#define max(a,b) (((a) > (b)) ? (a) : (b))
#define abs(x) ((x) < 0 ? -(x) : (x))
#define INF 0x3f3f3f3f
#define delta 0.85
#define eps 1e-3
#define PI 3.14159265358979323846
#define MAX_N 2010
using namespace std;
int N;
int A[MAX_N], B[MAX_N], dp[MAX_N];
int main(){
while(~scanf("%d", &N)){
for(int i = 0; i < N; i++){
scanf("%d", A + i);
B[i] = A[i];
}
sort(B, B + N);
int res = INF;
// 升序 dp
for(int i = 0; i < N; i++) dp[i] = abs(A[0] - B[i]);
for(int i = 1; i < N; i++){
dp[0] += abs(A[i] - B[0]);
for(int j = 1; j < N; j++){
dp[j] = min(dp[j], dp[j - 1] - abs(A[i] - B[j - 1])) + abs(A[i] - B[j]);
}
}
for(int i = 0; i < N; i++) res = min(res, dp[i]);
// 降序 dp
for(int i = 0; i < N; i++) dp[i] = abs(A[0] - B[i]);
for(int i = 1; i < N; i++){
dp[N - 1] += abs(A[i] - B[N - 1]);
for(int j = N - 2; j >= 0; j--){
dp[j] = min(dp[j], dp[j + 1] - abs(A[i] - B[j + 1])) + abs(A[i] - B[j]);
}
}
for(int i = 0; i < N; i++) res = min(res, dp[i]);
printf("%d\n", res);
}
return 0;
}