洛谷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 ",ans) ; 45 return 0 ; 46 }