• bzoj 1705: [Usaco2007 Nov]Telephone Wire 架设电话线——dp


    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。
    ————————————————————————————
    f[i][j]=min(f[i-1][k]+abs(j-k)*c+(h[i]-j)*(h[i]-j);
    我们可以分两类 
    1 j>k f[i][j]=min(f[i-1][k]-c*k+c*j+(h[i]-j)*(h[i]-j)
    可以发现转移方程与k无关 所以可以维护前缀min'就好了
    j < k 是差不多的维护一下后缀mn就可以了
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using std::min;
    using std::max;
    const int M=1e5+7,inf=0x3f3f3f3f;
    int read(){
        int ans=0,f=1,c=getchar();
        while(c<'0'||c>'9'){if(c=='-') f=-1; c=getchar();}
        while(c>='0'&&c<='9'){ans=ans*10+(c-'0'); c=getchar();}
        return ans*f;
    }
    int n,c,ans,mn;
    int h[M],f[M][107];
    int main(){
        n=read(); c=read();
        for(int i=1;i<=n;i++) h[i]=read();
        memset(f,0x3f,sizeof(f));
        for(int i=h[1];i<=100;i++) f[1][i]=(h[1]-i)*(h[1]-i);
        for(int k=2;k<=n;k++){
            mn=inf;
            for(int i=h[k-1];i<max(h[k-1],h[k]);i++) mn=min(mn,f[k-1][i]-c*i);
            for(int i=h[k];i<=100;i++){
                mn=min(mn,f[k-1][i]-c*i);
                f[k][i]=mn+c*i+(h[k]-i)*(h[k]-i);
            }
            mn=inf;
            for(int i=100;i>=h[k];i--){
                if(i>=h[k-1]) mn=min(mn,f[k-1][i]+c*i);
                f[k][i]=min(f[k][i],mn-c*i+(h[k]-i)*(h[k]-i));
            }
        }
        ans=inf;
        for(int i=1;i<=100;i++) ans=min(ans,f[n][i]);
        printf("%d
    ",ans);
        return 0;
    }
    View Code
  • 相关阅读:
    HDU2222 自动机(学习中)
    POJ 2289(多重匹配+二分)
    POJ 1486二分图的必要边
    二分图
    2015陕西 并查集
    Hdu2680 最短路
    函数调用约定
    用01随机函数构造[a,b]整数范围随机数
    hello
    Ubuntu 16.04 install R language
  • 原文地址:https://www.cnblogs.com/lyzuikeai/p/7570025.html
Copyright © 2020-2023  润新知