蹦蹦跳跳结束后,cxt回头看看本身走过的路坑坑洼洼的,心中很是不爽,他表示要把这段路的路面高度修成单调上升的或者单调降低的,整条路能够当作 N段,N个整数A1,…..,An(1<=n<=2000)依次描述了每一段路的高度(0<=Ai<=1000000000)。 但愿找到一个刚好含N个元素的不上升或不降低的序列B1,……,Bn,做为修过的路中每一个路段的高度。ios
因为将每一段路垫高或挖低一个单位消耗的体力相同,因而能够表示为:spa
|A1-B1|+|A2-B2|+…..+|An-Bn|code
请你计算一下,要修好这段道路,最少消耗多少体力。消耗的整体力不会超过2^31-1orm
输入文件的第一行仅有一正整数N,如下的N行每行一个整数Ai,表示路面的高度。排序
输出文件仅有一个正整数,表示若是把路修成高度不上升或不降低的最小花费ip
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。ci
================================it
题解正文io
================================class
题目分析
这是一道动态规划题目,求最小花费使道路变成不严格单调递增或不严格单调递减,数据大小用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; }