【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;
}
原文地址:https://www.cnblogs.com/dyhaohaoxuexi/p/14215260.html