洛谷P2893 [USACO08FEB]修路Making the Grade

洛谷P2893 [USACO08FEB]修路Making the Grade
这里有一个结论就是修改后的道路高度在原来的那些道路的高度中,出现过(修改后为了节省花费,
肯定数字要尽量向那些没修改过的靠近,)
所以我们把所有出现过的道路高度离散化,存在b数组中b[j]表示第j大的高度。
我们用f[i][j]将前i段变作不下降序列,且第j段道路的高度为b[j]时的最小花费,显而易见,
f[i][j]=min(f[i-1][k])+abs(a[i]-b[j])(1<=k<=j)其中a[i]表示第i段路原本的高度。
然而如果枚举k的话,你会发现时间复杂度为n^3。为了解决这个问题,我们发现min(f[i-1][k])
是可以在做第i-1段路段的时候处理出来的,(这个还是看代码吧。)所以复杂度就成了n^2。
我表示懒得用滚动数组,所以开了二维。。。
处理不上升序列的话和这个差不多。

 

 1 #include <bits/stdc++.h> 
 2 #define For(i,j,k) for(int i=j;i<=k;i++) 
 3 #define LL long long 
 4 using namespace std ; 
 5 
 6 inline int read() 
 7 {
 8     int x = 0 , f = 1 ; 
 9     char ch = getchar() ; 
10     while(ch<'0'||ch>'9') { if(ch=='-') f = -1 ; ch = getchar() ; } 
11     while(ch>='0'&&ch<='9') { x = x * 10+ch-48 ; ch = getchar() ; } 
12     return x * f ;  
13 }
14 
15 const int N = 2011,inf = 1e9 ; 
16 int n,ans ; 
17 int a[N],b[N],f[N][N],minf[N][N] ; 
18 
19 inline void SWAP() 
20 {
21     For(i,1,n/2) swap(a[i],a[n-i+1]) ; 
22 }
23 
24 inline void dp() 
25 {
26     For(i,1,n) minf[0][i] = 0 ; 
27     For(i,1,n) 
28       For(j,1,n) {
29           f[i][j] = minf[i-1][j]+ abs( b[j]-a[i] ) ;  
30           if(j!=1) minf[i][j] = min(f[i][j],minf[i][j-1]) ; 
31           else minf[i][j] = f[i][j] ; 
32       }
33     For(i,1,n) 
34         if( ans > f[n][i] ) ans = f[n][i] ; 
35 }
36 
37 int main() 
38 {
39     n = read() ; 
40     For(i,1,n) a[ i ] = read(),b[ i ] = a[ i ] ;  
41     sort(b+1,b+n+1) ; 
42     ans = inf ; 
43     dp() ;  SWAP() ; dp() ; 
44     printf("%d\n",ans) ; 
45     return 0 ; 
46 }

 

posted @ 2017-09-05 13:14  third2333  阅读(155)  评论(0编辑  收藏  举报