zoukankan      html  css  js  c++  java
  • 分级(线性dp)

    题目:

    给定长度为N的序列A,构造一个长度为N的序列B,满足:

    1、B非严格单调,即B1B2BNB1B2BN
    2、最小化 S=Ni=1|AiBi|

    只需要求出这个最小值S。

    输入格式

    第一行包含一个整数N。

    接下来N行,每行包含一个整数Ai

    输出格式

    输出一个整数,表示最小S值。

    数据范围

    1N2000
    1|Ai|10^9

    输入样例:

    7
    1
    3
    2
    4
    5
    3
    9
    

    输出样例:

    3

    解题报告:这是一道dp的题目,咱们首先要保证的就是这个b序列应该是非严格单调的,要求他的差值的绝对值之和最小,所以咱们就要尽可能地满足最长上升子序列(维护最小地花费),
    先把a数组存进另一个数组里,进行离散化处理,别的题解说的是数据的范围过大且数目较少,但是我没有很理解这点,维护地dp数组,dp[i][j]代表地就是前i个数以b[j]作为结束地最小
    花费,这里的貌似只需要维护递增的就可以,不需要去处理递减的情况


    ac代码:
     1 #include<iostream>
     2 #include<algorithm>
     3 #include<cstring>
     4 #include<cstdio>
     5 #include<cmath>
     6 using namespace std;
     7 typedef long long ll;
     8 
     9 const int maxn=2100;
    10 ll a[maxn],b[maxn];
    11 ll dp[maxn][maxn];
    12 int n;
    13 //dp[i][j] 代表的是前i个数字花费最小,并且以num[j]结尾的最小花费
    14 //由于数字的范围很大,但是数字的数目比较少,因此可以进行离散化,把数字映射到区间上 
    15 int main()
    16 {
    17     scanf("%d",&n);
    18     for(int i=1;i<=n;i++)
    19      {
    20          scanf("%lld",&a[i]);    
    21         b[i]=a[i];        
    22     }
    23     sort(b+1,b+1+n);
    24     int m=unique(b+1,b+1+n)-b-1;
    25     memset(dp,0,sizeof(dp));
    26     for(int i=1;i<=n;i++)
    27     {
    28         ll tmp=dp[i-1][1];
    29         for(int j=1;j<=m;j++)
    30         {
    31             tmp=min(tmp,dp[i-1][j]);
    32             dp[i][j]=tmp+abs(a[i]-b[j]);
    33         }
    34     }
    35     ll ans=0x3f3f3f3f;
    36     for(int i=1;i<=m;i++)
    37         ans=min(ans,dp[n][i]);
    38     printf("%lld
    ",ans); 
    39     
    40         
    41 }
     
  • 相关阅读:
    菜鸟涂鸦作品展_No.29
    菜鸟涂鸦作品展_No.27
    菜鸟涂鸦作品展_No.26
    关注的前沿动态
    货币转换
    第二周总结
    老鼠
    71 打印沙漏
    学习总结0.0
    第五周作业
  • 原文地址:https://www.cnblogs.com/Spring-Onion/p/11355525.html
Copyright © 2011-2022 走看看