zoukankan      html  css  js  c++  java
  • 【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 }
  • 相关阅读:
    页面抛出的"Unable to validate data"错误
    oracle的sqlnet.ora,tnsnames.ora,listener.ora三个配置文件 water
    Win7下完全卸载Oracle 11g water
    抛出多个异常 water
    【转】有关Oracle随机字符串的生成方法及具体应用 water
    【转】oracle 中随机取一条记录的两种方法 water
    【转】Oracle索引列NULL值引发执行计划该表的测试示例 water
    Oracle 取随机数 water
    dbms_output.put_line长度限制问题 water
    oracle 监听启动、停止、查看命令 water
  • 原文地址:https://www.cnblogs.com/iiyiyi/p/6055488.html
Copyright © 2011-2022 走看看