【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 }
原文地址:https://www.cnblogs.com/iiyiyi/p/6055488.html