【DP】BZOJ1592-[Usaco2008 Feb]Making the Grade 路面修整
我活着从期中考试回来了!!!!!!!!!备考NOIP!!!!!!!!!
【题目大意】
给出n个整数a1~an,修改一个数的代价为修改前后差的绝对值,问修改成不下降序列或者不上升序列的最小总代价。
【思路】
预处理b[],为排序后的a[]。
f[i][j]表示前i个数,其中第i个数字修改为第j个大的数的最小代价。f[i][j]=min(f[i-1][k])+abs(a[i]-b[j]) (1<=k<=j)。b[]正反分别来一次。
这样是O(n^3)的,不过我们发现f[i-1][k]的最小值是可以直接保留下来的,所以最后复杂度为O(n)。
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int INF=1e9; 4 const int MAXN=2000+50; 5 int n,f[MAXN][MAXN],a[MAXN],b[MAXN],tmp[MAXN],premin[MAXN]; 6 7 void dp() 8 { 9 memset(premin,0,sizeof(premin)); 10 for (int i=1;i<=n;i++) 11 for (int j=1;j<=n;j++) 12 { 13 f[i][j]=premin[j]+abs(a[i]-b[j]); 14 if (j==1) premin[j]=f[i][j];else premin[j]=min(premin[j-1],f[i][j]); 15 } 16 } 17 18 void init() 19 { 20 scanf("%d",&n); 21 for (int i=1;i<=n;i++) scanf("%d",&a[i]); 22 } 23 24 void solve() 25 { 26 int ans=INF; 27 for (int i=1;i<=n;i++) b[i]=a[i]; 28 sort(b+1,b+n+1); 29 dp(); 30 for (int i=1;i<=n;i++) ans=min(ans,f[n][i]); 31 for (int i=1;i<=n;i++) tmp[i]=b[i]; 32 for (int i=1;i<=n;i++) b[n-i+1]=tmp[i]; 33 dp(); 34 for (int i=1;i<=n;i++) ans=min(ans,f[n][i]); 35 printf("%d",ans); 36 } 37 38 int main() 39 { 40 init(); 41 solve(); 42 return 0; 43 }
忽然想到b[]中有一些数可能是重复的,所以可以离散化一下。快了一丢丢。
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int INF=1e9; 4 const int MAXN=2000+50; 5 int n,m,f[MAXN][MAXN],a[MAXN],b[MAXN],tmp[MAXN],premin[MAXN]; 6 7 void dp() 8 { 9 memset(premin,0,sizeof(premin)); 10 for (int i=1;i<=n;i++) 11 for (int j=1;j<=m;j++) 12 { 13 f[i][j]=premin[j]+abs(a[i]-b[j]); 14 if (j==1) premin[j]=f[i][j];else premin[j]=min(premin[j-1],f[i][j]); 15 } 16 } 17 18 void init() 19 { 20 scanf("%d",&n); 21 for (int i=1;i<=n;i++) scanf("%d",&a[i]); 22 } 23 24 void solve() 25 { 26 int ans=INF; 27 for (int i=1;i<=n;i++) b[i]=a[i]; 28 sort(b+1,b+n+1); 29 m=unique(b+1,b+n+1)-(b+1); 30 dp(); 31 for (int i=1;i<=m;i++) ans=min(ans,f[n][i]); 32 for (int i=1;i<=m;i++) tmp[i]=b[i]; 33 for (int i=1;i<=m;i++) b[n-i+1]=tmp[i]; 34 dp(); 35 for (int i=1;i<=m;i++) ans=min(ans,f[n][i]); 36 printf("%d",ans); 37 } 38 39 int main() 40 { 41 init(); 42 solve(); 43 return 0; 44 }