Making the Grade---poj3666(类似离散化+dp)

题目链接:http://poj.org/problem?id=3666

题意是给出一组数,每个数代表当前位置的地面高度,问把路径修成非递增或者非递减,需要花费的最小代价?

///用dp[i][j]表示:前i个数构成的序列,这个序列最大值为j,dp[i][j]的值代表相应的cost。

///dp[i][j]=abs(j-w[i])+min(dp[i-1][k]);(k<=j)

///i-1构成的序列,最大值是k + (j-w[i])变成此步需要的花费

因为要把路径修成非递减路径,所以a[j]>a[k],所以我们要三重循环来搞,时间复杂度O(n^3)。

如果我们对原来数列进行复制排序的话,a[j]>a[k]就转化为了j>k,这样就成功的把时间复杂度从O(n^3)降为O(n^2)。

空间复杂度也可以用滚动数组从O(n^2)变为O(n)。

#include<stdio.h>
#include<iostream>
#include<string.h>
#include<algorithm>
using namespace std;
#define N 2100
#define INF 0x3f3f3f3f
#define met(a) memset(a, 0, sizeof(a))
//1061109567 0x3f3f3f3f
//268435455  0xfffffff  本题用这个会错的;因为它不够大;害的我wa了那么多次-_-;
int n, dp[N][N], a[N], b[N];

int main()
{
    while(scanf("%d", &n)!=EOF)
    {
        met(a); met(b);
        for(int i=1; i<=n; i++)
        {
            scanf("%d", &a[i]);
            b[i] = a[i];
        }
        sort(b+1, b+n+1);
        for(int i=1; i<=n; i++)
        {
            int Min = INF;
            for(int j=1; j<=n; j++)
            {
                Min=min(Min, dp[i-1][j]);
                dp[i][j] = Min + abs(a[i] - b[j]);
            }
        }
        int ans = INF;
        for(int i=1; i<=n; i++)
            ans=min(ans, dp[n][i]);
        printf("%d
", ans);
    }
    return 0;
}

  

原文地址:https://www.cnblogs.com/zhengguiping--9876/p/4959114.html