蹦蹦跳跳结束后,cxt回头看看自己走过的路坑坑洼洼的,心中非常不爽,他表示要把这段路的路面高度修成单调上升的或者单调下降的,整条路可以看成 N段,N个整数A1,…..,An(1<=n<=2000)依次描述了每一段路的高度(0<=Ai<=1000000000)。 希望找到一个恰好含N个元素的不上升或不下降的序列B1,……,Bn,作为修过的路中每个路段的高度。
由于将每一段路垫高或挖低一个单位消耗的体力相同,于是可以表示为:
|A1-B1|+|A2-B2|+…..+|An-Bn|
请你计算一下,要修好这段道路,最少消耗多少体力。消耗的总体力不会超过2^31-1
输入文件的第一行仅有一正整数N,以下的N行每行一个整数Ai,表示路面的高度。
输出文件仅有一个正整数,表示如果把路修成高度不上升或不下降的最小花费
7 1 3 2 4 5 3 9
3
将第一个高度为3的路段的高度减少为2,将第二个高度为3的路段的高度增加到5,总花费为|2-3|+|5-3|=3,并且各路段的高度为一个不下降序列 1,2,2,4,5,5,9。
================================
题解正文
================================
题目分析
这是一道动态规划题目,求最小花费使道路变成不严格单调递增或不严格单调递减,数据大小用int即可。
#include<iostream> #include<cmath> #include<algorithm> using namespace std; int n,ans=1<<30,a[2005],c[2005],f[2005][2005],g[2005][2005]; void init() { cin>>n; for(int i = 1; i <= n ; ++i) { cin >> a[i]; c[i]=a[i]; } sort(c+1,c+n+1); } void sol() { for(int i = 1; i <= n; ++i) { for(int j = 1; j <= n; ++j) { f[i][j] = g[i-1][j] + abs(a[i]-c[j]); if(j == 1) g[i][j] = f[i][j]; else g[i][j] = min(f[i][j],g[i][j-1]); } } for(int i = 1; i <= n; ++i) ans = min(ans ,f[n][i]); } int main() { init(); sol();//算一遍递增 for(int i = 1; i <= n/2 ; ++i) swap(c[i],c[n-i+1]); sol();//算一遍递减 cout<<ans; }
SJTU OJ 1282 修路 题解,布布扣,bubuko.com
原文地址:http://my.oschina.net/xueyang/blog/291324