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;
}
posted @ 2019-05-14 23:45  moxin0509  阅读(271)  评论(0编辑  收藏  举报