zoukankan      html  css  js  c++  java
  • 【bzoj1705】[Usaco2007 Nov]Telephone Wire 架设电话线 dp

    [Usaco2007 Nov]Telephone Wire 架设电话线

    Time Limit: 5 Sec  Memory Limit: 64 MB
    Submit: 487  Solved: 277
    [Submit][Status][Discuss]

    Description

    最近,Farmer John的奶牛们越来越不满于牛棚里一塌糊涂的电话服务 于是,她们要求FJ把那些老旧的电话线换成性能更好的新电话线。 新的电话线架设在已有的N(2 <= N <= 100,000)根电话线杆上, 第i根电话线杆的高度为height_i米(1 <= height_i <= 100)。 电话线总是从一根电话线杆的顶端被引到相邻的那根的顶端 如果这两根电话线杆的高度不同,那么FJ就必须为此支付 C*电话线杆高度差(1 <= C <= 100)的费用。当然,你不能移动电话线杆, 只能按原有的顺序在相邻杆间架设电话线。Farmer John认为 加高某些电话线杆能减少架设电话线的总花费,尽管这项工作也需要支出一定的费用。 更准确地,如果他把一根电话线杆加高X米的话,他得为此付出X^2的费用。 请你帮Farmer John计算一下,如果合理地进行这两种工作,他最少要在这个电话线改造工程上花多少钱。

    Input

    * 第1行: 2个用空格隔开的整数:N和C

    * 第2..N+1行: 第i+1行仅有一个整数:height_i

    Output

    * 第1行: 输出Farmer John完成电话线改造工程所需要的最小花费

    Sample Input

    5 2
    2
    3
    5
    1
    4
    输入说明:
    一共有5根电话线杆,在杆间拉电话线的费用是每米高度差$2。
    在改造之前,电话线杆的高度依次为2,3,5,1,4米。


    Sample Output

    15
    输出说明:
    最好的改造方法是:Farmer John把第一根电话线杆加高1米,把第四根加高2米,
    使得它们的高度依次为3,3,5,3,4米。这样花在加高电线杆上的钱是$5。
    此时,拉电话线的费用为$2*(0+2+2+1) = $10,总花费为$15。

    HINT

     

    Source

     

    由题意易得出DP方程

    f[i][j] = min(f[i-1][k]+|j-k|*c+(a[i]-j)*(a[i]-j))
    时间复杂度为O(N*100*100)

    摘出与k无关项得
    f[i][j] = min(f[i-1][k]+|j-k|*c) + (a[i]-j)*(a[i]-j)

    记P = min(f[i-1][k]+|j-k|*c) , Q = (a[i]-j)*(a[i]-j)
    则f[i][j] = P + Q

    易知
    P = min(A,B),其中
    A = min(f[i-1][k]+(j-k)*c) (k<=j)
    B = min(f[i-1][k]+(k-j)*c) (k>j)

    A = min(f[i-1][k]-k*c) + j*c
    B = min(f[i-1][k]+k*c) - j*c

    记C[X][i] = min(f[X][k] - k*c)  k∈[1,i]
    记D[X][i] = min(f[X][k] + k*c)  k∈[i,n]

    则A = C[i-1][j] + j*c
    则B = D[i-1][j+1] - j*c
    写的好:http://blog.csdn.net/icecathy/article/details/52765627
     1 #include<cstring>
     2 #include<cmath>
     3 #include<algorithm>
     4 #include<iostream>
     5 #include<cstdio>
     6 
     7 #define N 100007
     8 #define H 107
     9 #define INF 0x3f3f3f3f
    10 typedef long long ll;
    11 using namespace std;
    12 inline int read()
    13 {
    14     int x=0,f=1;char ch=getchar();
    15     while(ch>'9'||ch<'0'){if (ch=='-') f=-1;ch=getchar();}
    16     while(ch<='9'&&ch>='0'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
    17     return x*f;
    18 }
    19 int n,c;
    20 int h;
    21 int height[N];
    22 int p,q,a,b,C[H],d[H];
    23 int f[N][H];
    24 int main()
    25 {
    26     scanf("%d%d",&n,&c);
    27     for (int i=1;i<=n;i++) 
    28         scanf("%d",&height[i]);
    29     h=height[1];
    30     for (int i=1;i<=n;i++)
    31         h=max(h,height[i]);
    32     h=min(h,100),memset(f,0x3f,sizeof(f));
    33     for (int i=1;i<=n;i++)
    34     {
    35         if(i==1) 
    36             for (int j=height[1];j<=h;j++)
    37                 f[1][j]=(j-height[1])*(j-height[1]);
    38         else 
    39             for (int j=height[i];j<=h;j++)
    40             {
    41                 q=(j-height[i])*(j-height[i]);
    42                 a=C[j]+j*c;
    43                 b=d[j+1]-j*c;
    44                 p=min(a,b);
    45                 f[i][j]=p+q;
    46             }
    47         C[0]=d[h+1]=INF;
    48         for (int j=1;j<=h;j++)
    49             C[j]=min(C[j-1],f[i][j]-j*c);
    50         for (int j=h;j>=1;j--)
    51             d[j]=min(d[j+1],f[i][j]+j*c);    
    52     }
    53     int ans=INF;
    54     for (int i=1;i<=h;i++)
    55         ans=min(ans,f[n][i]);
    56     printf("%d
    ",ans);
    57 }
  • 相关阅读:
    POJ1741 Tree
    BZOJ3674 可持久化并查集加强版
    BZOJ3673 可持久化并查集 by zky
    BZOJ3174 [Tjoi2013]拯救小矮人
    BZOJ2733 永无乡【splay启发式合并】
    AtCoder Grand Contest 007 E:Shik and Travel
    BZOJ2599:[IOI2011]Race
    AtCoder Regular Contest 063 E:Integers on a Tree
    SPOJ1825:Free Tour II
    AtCoder Grand Contest 012 C:Tautonym Puzzle
  • 原文地址:https://www.cnblogs.com/fengzhiyuan/p/8098409.html
Copyright © 2011-2022 走看看