• 解题报告 telewire


    Telewire

     最近,约翰的奶牛们越来越不满足于牛棚里一塌糊涂的电话服务,于是,她们要求约翰把那些老旧的电话线换成性能更好的新电话线。新的电话线架设在已有的n根电话线杆上,第i根电话线的高度为hi,(1=<hi<=100)。电话线总是从一根电话线杆的顶端被引到相邻的那根的顶端,如果这两根电话线杆的高度hi和hj不同,那么约翰就必须支付c*abs(hi-hj)的费用,当然,你不能移动电话线杆,只能按照原有的顺序在相邻杆间架设电话线。

      加高某些电话线杆能减少架设电话线的总费用,尽管这项工作也需要支付一定的费用。更准确的说,如果他把一根电话线杆加高x米的话,他需要付出x^2费用。

     请你帮约翰计算一下,如果合理的进行这两项工作,他最少要在这个电话线改造工程中花多少钱。

    输入说明

      第一行输入两个数n和c,含义如上

    接下来n行,每行一个整数hi

    输出说明

      输出约翰完成电话线改造工程需要花费的最小费用

    输入样例

    5 2

    2

    3

    5

    1

    4

    输出样例

    15

    数据范围

    N<=100000

    C<=100;

    Hi<=100;

     

     

     

    一个易得的方程是f[i,j]表示第i个电线杆长度为j时的最小费用

    f[i,j]:=min(f[i-1,k]+sqr(a[i]-j)+abs(j-k)*c);

    观察方程可以转化为等价方程组

    if j<=k 那么 f[i,j]:=min(f[i-1,k]+k*c)+sqr(a[i]-j)-j*c

    if j>k    那么 f[i,j]:=min(f[i-1,k]-k*c)+sqr(a[i]-j)+j*c

    min(f[i-1,k]+k*c)min(f[i-1,k]-k*c)是可以用滚动数组来搞定的

    具体实现是这样:用 low[j] 表示min(f[i-1,k]-k*c), high[j] 表示 min(f[i-1,k]+k*c) 。(k<=j) 然后可以预处理出 i=1 时的 low[] 和 high[] ,然后更新 f[i,j] 的时候,顺便更新一下对应的 low[] high[] 也就是滚动数组。

    然后,代码 ???

    program telewire;

     

    const

      maxn=100001;

      maxint=99999999;

     

    var

      f:array[-1..maxn,-1..101] of longint;

      high,low:array[-1..100] of longint;

      a:array[-1..maxn] of longint;

      n,c,up,down,i,j,k,ans:longint;

     

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

    begin

      if a<b then exit(a) else exit(b);

    end;

     

    begin

      readln(n,c);

      up:=0;

      down:=101;

      for i:=1 to n do

        begin

          readln(a[i]);

          if a[i]>up then up:=a[i];

          if a[i]<down then down:=a[i];

        end;

     

      filldword(f,sizeof(f)>>2,maxlongint>>2); 

     

      for i:=a[1] to 100 do

        f[1,i]:=(a[1]-i)*(a[1]-i);

     

      fillchar(low,sizeof(low),63);

      low[up]:=f[1,up]+up*c;

      for k:=up-1 downto down do

         low[k]:=min(low[k+1],f[1,k]+k*c);

     

      fillchar(high,sizeof(high),63);

      high[down]:=f[i,down]-down*c;

      for k:=down+1 to up do

         high[k]:=min(high[k-1],f[1,k]-k*c);

     

      for i:=2 to n do

        begin

          for j:=a[i] to up do

            begin

              f[i,j]:=min(f[i,j],low[j]+(a[i]-j)*(a[i]-j)-j*c);

              f[i,j]:=min(f[i,j],high[j]+(a[i]-j)*(a[i]-j)+j*c);

            end;

     

          fillchar(low,sizeof(low),63);

          low[up]:=f[i,up]+up*c;

          for k:=up-1 downto down do

            low[k]:=min(low[k+1],f[i,k]+k*c);

     

          fillchar(high,sizeof(high),63);

          high[down]:=f[i,down]-down*c;

          for k:=down+1 to up do

            high[k]:=min(high[k-1],f[i,k]-k*c);

        end;

     

      ans:=maxlongint;

     

      for i:=down to up do

        if ans>f[n,i] then ans:=f[n,i];

     

      writeln(ans);

    end.

     

     

     

     

  • 相关阅读:
    利用WebClient实现自动添写、提交表单
    动态.net代码生成器遇到的问题
    unicode
    使用using清理非托管资源
    C#中解决插入数据库的某个字段类型为datetime 为空
    JQuery中根据属性或属性值获得元素
    Access 的top和order by 的问题
    JavaScript escape() 函数
    Asp.net嵌套
    合并程序集时出错的问题ILMerge.Merge.ERROR...
  • 原文地址:https://www.cnblogs.com/SueMiller/p/2232038.html
Copyright © 2020-2023  润新知