zoukankan      html  css  js  c++  java
  • 解题报告 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.

     

     

     

     

  • 相关阅读:
    今天面试一些程序员(新,老)手的体会
    UVA 10635 Prince and Princess
    poj 2240 Arbitrage
    poj 2253 Frogger
    poj 2485 Highways
    UVA 11258 String Partition
    UVA 11151 Longest Palindrome
    poj 1125 Stockbroker Grapevine
    poj 1789 Truck History
    poj 3259 Wormholes
  • 原文地址:https://www.cnblogs.com/SueMiller/p/2232038.html
Copyright © 2011-2022 走看看