• Making the Grade (bzoj1592)


    ╮(╯▽╰)╭一道挺裸地DP,为什么考试的时候想不出来呢???可能是我太弱了吧。。。

    题目描述

          FJ打算好好修一下农场中某条凹凸不平的土路。按奶牛们的要求,修好后的路面高度应当单调上升或单调下降,也就是说,高度上升与高度下降的路段不能同时出现在修好的路中。 整条路被分成了N段,N个整数A_1, ... , A_N (1 <= N <= 2,000)依次描述了每一段路的高度(0 <= A_i <= 1,000,000,000)。FJ希望找到一个恰好含N个元素的不上升或不下降序列B_1, ... , B_N,作为修过的路中每个路段的高度。由于将每一段路垫高或挖低一个单位的花费相同,修路的总支出可以表示为: |A_1 - B_1| + |A_2 - B_2| + ... + |A_N - B_N| 请你计算一下,FJ在这项工程上的最小支出是多少。FJ向你保证,这个支出不会超过2^31-1。

    输入

    * 第1行: 输入1个整数:N * 第2..N+1行: 第i+1行为1个整数:A_i

    输出

    * 第1行: 输出1个正整数,表示FJ把路修成高度不上升或高度不下降的最小花费

    样例输入

    7
    1
    3
    2
    4
    5
    3
    9

    样例输出

    3

    提示

    FJ将第一个高度为3的路段的高度减少为2,将第二个高度为3的路段的高度增加到5,总花费为|2-3|+|5-3| = 3,并且各路段的高度为一个不下降序列 1,2,2,4,5,5,9。

    一看数据范围知道是DP,然后在瞅一眼发现高度要离散;

      状态转移方程:

           f[i][j]=min(f[i][j],f[i-1][j]+abs(w[i]-ma[j]));
                f[i][j]=min(f[i][j],f[i][j-1]);
    第一位是前i个,第二维代表离散后高度的大小,或者说是第j大的高度;
    然后推的一个都用前一维来推,所以不会出故障。
     
    附代码:
      
     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<map>
     6 using namespace std;
     7 map<int,int>ma;
     8 int read(){
     9     int sum=0;char ch=getchar();
    10     while(ch<'0'||ch>'9') ch=getchar();
    11     while(ch>='0'&&ch<='9'){sum=sum*10+ch-'0';ch=getchar();}
    12     return sum;
    13 }
    14 int n,num;
    15 int w[2001],f[2001][2001],h[2001];
    16 void dp1(){
    17     for(int i=0;i<=num;++i)
    18         f[0][i]=0;
    19     for(int i=1;i<=n;++i){
    20         for(int j=0;j<=num;++j){
    21             f[i][j]=min(f[i][j],f[i-1][j]+abs(w[i]-ma[j]));
    22             f[i][j]=min(f[i][j],f[i][j-1]);
    23         }
    24     }
    25     cout<<f[n][num]<<endl;
    26 }
    27 int main(){
    28 //  freopen("grading.in","r",stdin);
    29     //freopen("grading.out","w",stdout);
    30     memset(f,0x3f,sizeof(f));
    31     n=read();
    32     for(int i=1;i<=n;++i)
    33         w[i]=read(),h[i]=w[i];
    34     sort(h+1,h+n+1);ma[0]=0;
    35     for(int i=1;i<=n;++i)
    36         if(h[i]!=h[i-1])    
    37             ma[++num]=h[i];
    38     dp1();
    39      //while(1);
    40 }
  • 相关阅读:
    java命令模式;
    java 基于Socket实现QQ聊天小系统
    java 考试系统,类似驾考宝典
    jmeter之认识元器件及功能 大杂烩
    java GUI
    Codeforces Round #382 (Div. 1) A. Tennis Championship
    Hrbust-1316-移动 II(广度优先搜索 路径记录)
    Hrbust-1942-this is bad problom(搜索)
    Hrbust-1287-数字去重和排序II(set集合容器应用)
    Hrbust-1012-Catch That Cow(广搜BFS入门)
  • 原文地址:https://www.cnblogs.com/Maplers/p/7276947.html
Copyright © 2020-2023  润新知