1. 程式人生 > >bzoj 1592 路面修整

bzoj 1592 路面修整

Description

FJ打算好好修一下農場中某條凹凸不平的土路。按奶牛們的要求,修好後的路面高度應當單調上升或單調下降,也 就是說,高度上升與高度下降的路段不能同時出現在修好的路中。 整條路被分成了N段,N個整數A_1, ... , A_N  (1 <= N <= 2,000)依次描述了每一段路的高度(0 <= A_i <= 1,000,000,000)。FJ希望找到一個恰好含N個元素的 不上升或不下降序列B_1, ... , B_N,作為修過的路中每個路段的高度。由於將每一段路墊高或挖低一個單位的花 費相同,修路的總支出可以表示為: |A_1 - B_1| + |A_2 - B_2| + ... + |A_N - B_N| 請你計算一下,FJ在這 項工程上的最小支出是多少。FJ向你保證,這個支出不會超過2^31-1。

Input

* 第1行: 輸入1個整數:N  * 第2..N+1行: 第i+1行為1個整數:A_i

Output

* 第1行: 輸出1個正整數,表示FJ把路修成高度不上升或高度不下降的最小花費

Sample Input

7
1
3
2
4
5
3
9

Sample Output

//FJ將第一個高度為3的路段的高度減少為2,將第二個高度為3的路段的高度增加到5,總花費為|2-3|+|5-3| = 3
,並且各路段的高度為一個不下降序列 1,2,2,4,5,5,9。

HINT

2017.11.07新加兩組資料By 

Alextokc

Source

Gold

思路: 本提為動態規劃,需要用到一個結論,就是最後的數一定是原數中的一些數,這樣就可以在$n^{2}$的時間內解決了。
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define R  register int
 4 #define rep(i,a,b) for(R i=a;i<=b;i++)
 5 #define Rep(i,a,b) for(R i=a;i>=b;i--)
 6 #define ms(i,a)    memset(a,i,sizeof(a))
 7
#define LL long long 8 template<class T>void read(T &x){ 9 x=0; char c=0; 10 while (!isdigit(c)) c=getchar(); 11 while (isdigit(c)) x=x*10+(c^48),c=getchar(); 12 } 13 int const N=2000+3; 14 LL const inf=1e12; 15 int a[N],b[N],n,m; 16 LL dp[N][N],f[N][N]; 17 void solve(){ 18 f[1][0]=inf; 19 rep(i,1,m) dp[1][i]=abs(a[1]-b[i]),f[1][i]=min(f[1][i-1],dp[1][i]); 20 rep(i,2,n){ 21 rep(j,1,m) dp[i][j]=abs(a[i]-b[j])+f[i-1][j]; 22 f[i][0]=inf; 23 rep(j,1,m) f[i][j]=min(f[i][j-1],dp[i][j]); 24 } 25 } 26 int main(){ 27 read(n); 28 rep(i,1,n) read(a[i]),b[i]=a[i]; 29 sort(b+1,b+n+1); 30 m=unique(b+1,b+n+1)-b-1; 31 solve(); 32 LL ans=inf; 33 rep(i,1,m) ans=min(dp[n][i],ans); 34 rep(i,1,m/2) swap(b[i],b[m-i+1]); 35 solve(); 36 rep(i,1,m) ans=min(dp[n][i],ans); 37 cout<<ans<<endl; 38 return 0; 39 }
View Code