刷题——Making the Grade POJ - 3666

/*
题目大意:给定一堆连续山坡的高度,要求变换山坡的高度使得山坡高度非上升或非下降
花费为|a1-b1|+|a2-b2|+...+|an-bn| a为原高度,b为变换后的高度,求最小花费
对与ai不管是增高或是降低很明显的它的变化的高度与它前一个山坡ai-1,和后面所有的山坡有关[ai+1,an]
所以,为了使花费更少bi=aj,若bi不等于aj,那一定会有一个比bi更小的ak或者更大的al满足条件,且花费更少
所以bi在[a1,an]中
所以令bi=ai,将bi排个序
dp[i][j],表示ai变成bj时,前i-1个山坡的最小花费+abs(a[i]-b[j])
dp[i][j]=abs(a[i]-b[j])+min(dp[i-1][1~j])(满足要求)
min(dp[i-1][1~j])用一个数组优化一下转换成前j个数的最小值
*/
#include <stdio.h>
#include <algorithm>
#include <string.h>
using namespace std;
#define ll long long
#define INF 2*1e9
int n;
ll a[2005];
ll b[2005];
ll dp[2005];
ll d[2005];
ll abs(ll x,ll y){
    if(x>y){
        return x-y;
    }
    return y-x;
}
ll solve(){
    sort(b+1,b+1+n);
    ll minn=INF;
    for(int i=1;i<=n;i++){
        dp[i]=abs(a[1],b[i]);
        if(dp[i]<minn){
            minn=dp[i];
        }
        d[i]=minn;
    }
    for(int i=1;i<=n;i++){
        minn=INF;
        for(int j=1;j<=n;j++){
            dp[j]=d[j]+abs(a[i],b[j]);
            if(dp[j]<minn){
                minn=dp[j];
            }
            d[j]=minn;
        }
    }
    return minn;
}
int main(){
    while(~scanf("%d",&n)){
        for(int i=1;i<=n;i++){
            scanf("%I64d",&a[i]);
            b[i]=a[i];
        }
        printf("%I64d\n",solve());
    }
    return 0;
}
展开阅读全文

没有更多推荐了,返回首页