zoukankan      html  css  js  c++  java
  • 路面修整

    路面修整 

    【问题描述】

       

         大老板Mr. Yao打算好好修一下公司门口的那条凹凸不平的路。按照Mr. Yao的设想,修好后的路面高度应当单调上升或单调下降,也就是说,高度上升与高度下降的路段不能同时出现在修好的路中。

        整条路被分成了N段,N个整数A_1, ... , A_N (1 <= N <= 2,000)依次描述了每一段路的高度(0 <= A_i <= 1,000,000,000)。Mr. Yao希望找到一个恰好含N个元素的不上升或不下降序列B_1, ... , B_N,作为修过的路中每个路段的高度。由于将每一段路垫高或挖低一个单位的花费相同,修路的总支出可以表示为:

             |A_1 - B_1| + |A_2 - B_2| + ... + |A_N - B_N|

        请你计算一下,Mr. Yao在这项工程上的最小支出是多少。Mr. Yao向你保证,这个支出不会超过2^31-1。

    动态规划:

    分析一下需要知道的量:路面的位置,路面需要调整的高度,

    所以我们设f[i,j]表示到了路面为i的位置,高度为j,但它怎么由前面的转移过来呢,f[i,j]:=min(f[i,k])+abs(a[i]-j)

    它的状态有前方的状态转移过来:它i位置的高度为k,(K<=j),的最小代价,再加上将i位置调整到j高度的花费。

    K究竟是多少呢?有贪心的思想可知,调整时调整到原来某个高度一定最好(调整到与某个路面相同的高度,保证了不降或不升,但若调整到其他高度,那么代价一定又加上了比相同高度的多余代价),开一个b[i]数组,记录a[i]的高度,排序,f[i,j]:=min(f[i,k])+abs(a[i]-b[j])中的j含义变成了第j种高度,for i:=1 to n do (阶段)

            For j:=1 to n do (状态)

              For k:=1 to j do (决策)

    N^3的时间复杂度过不了,所以改变方程的含义f[i,j]:=min(f[i,j-1],f[i-1,j]+abs(a[i]-b[j]))此时f[i,j]表示到了路面为i的位置,高度小于或等于j,且符合题意。它由前方两种状态转移过来:1.第i-1种为j,则它的代价需要加上abs(a[i-b[j]]);2.f[i,j-1]表示j从1到n转移时记录的将第i段路高度设为小于或等于b[j-1]时最小值,每一次用当前状态表示最小,这样将时间复杂度降到了n^2;最后,由于不知道序列是不降或不升,所以将b[i]数组倒过来再做一遍不降的情况。俩次取min。

    代码实现:

    program exam;

    var

      a,tmp,c:array[0..2000] of longint;

      n,ans,i:longint;

      g,f:array[0..2000,0..2000] of longint;

    function min(a,b:longint):longint;

    begin

      if a>b then

        exit(b)

      else

        exit(a);

    end;

    procedure swap(var a,b:longint);

    var

      t:longint;

    begin

      t:=a;

      a:=b;

      b:=t;

    end; 

    procedure qsort(l,r:longint);

    var

      i,j,x:longint;

    begin

      i:=l;

      j:=r;

      x:=a[(l+r) div 2];

      repeat

        while x>a[i] then

          inc(i);

        while x<a[j] then

          dec(j);

        if i<=j then

        begin

          swap(a[i],a[j]);

          inc(i);

          dec(j);

        end;

      until i>j;

      if i<r then

        qsort(i,r);

      if l<j then

        qsort(l,j);

    end;

    procedure dp;

    var

      i,j::longint;

    begin

      for i:=1 to n do

        g[i,0]:=maxlongint;                // 初始化

      for i:=1 to n do

        for j:=1 to n do              //dp[i,j]:=min(dp[i-1,j]+abs(a[i]-c[j]),dp[i,j-1])

        begin

          f[i,j]:=g[i-1,j]+abs(a[i]-c[j]); // c 为排序后的数组

          g[i,j]:=min(f[i,j],g[i,j-1]);

        end; 

      ans:=min(ans,g[n,n]);

    end;

    begin

      ans:=maxlongint;

      readln(n);

      for i:=1 to n do

        readln(a[i]);

      tmp:=a;

      qsort(1,n);

      c:=a;

      a:=tmp;

      dp;

      writeln(ans);

    end.

  • 相关阅读:
    几款比较好用的思维导图工具
    单例模式的七种实现
    从中央仓库下载所想要的jar包
    单例模式实现的几种方式
    两个数组比较看看结果
    CSS 基础 例子 伪元素和伪类 & 区别
    CSS 基础 例子 背景色 & 背景图片
    CSS 基础 例子 水平 & 垂直对齐
    CSS 基础 例子 浮动float
    CSS 基础 例子 行高line-height
  • 原文地址:https://www.cnblogs.com/fengxiudong/p/6017305.html
Copyright © 2011-2022 走看看