Loading

【dp每日一题】POJ 3666 Making the Grade

大意:

给出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;
}
posted @ 2020-12-31 11:18  dyhaohaoxuexi  阅读(89)  评论(0编辑  收藏  举报