zoukankan      html  css  js  c++  java
  • [BZOJ1705] [Usaco2007 Nov]Telephone Wire 架设电话线

    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]$为前$i$个树,第$i$个高度是$j$的最小花费。

    显然$f[i][j] = min(f[i - 1][k] + (j - h[i])^2 +C imes (k - j))$。

    这样是$O(N imes h^2)$的不太可过。

    我们拆开发现

    $f[i][j] = f[i-i][k]+C imes j - C imes k,k leq j$

    $f[i][j] = f[i-1][k]-C imes j + C imes k, k > j$.

    发现其实就是维护$f[i-1][k]-C imes k$的前缀最小值和$f[i-1][k]+c imes k$的后缀最大值。

    于是就可以$O(N imes h)$做出。


    #include <iostream>
    #include <cstdio> 
    #include <algorithm>
    #include <cstring>
    #include <queue>
    #include <cmath>
    using namespace std;
    #define reg register
    #define gc getchar
    inline int read() {
        int res=0;char ch=gc();bool fu=0;
        while(!isdigit(ch))fu|=(ch=='-'), ch=gc();
        while(isdigit(ch))res=(res<<3)+(res<<1)+(ch^48), ch=gc();
        return fu?-res:res;
    }
    #define N 100005
    #define ll long long
    int n, C;
    int h[N];
    ll f[N][105];
    ll ans = 1e16;
    ll mnt[105], mnw[105];
    
    int main()
    {
        n = read(), C = read();
        for (reg int i = 1 ; i <= n ; i ++) h[i] = read();
        for (reg int i = 1 ; i <= n ; i ++)
            for (reg int j = 1 ; j <= 100 ; j ++)
                f[i][j] = 1e16;
        for (reg int i = h[1] ; i <= 100 ; i ++) f[1][i] = (h[1] - i) * (h[1] - i);
        
        for (reg int i = 2 ; i <= n ; i ++)
        {
            memset(mnt, 0x7f, sizeof mnt), memset(mnw, 0x7f, sizeof mnw);
            for (reg int j = 1 ; j <= 100 ; j ++) mnt[j] = min(mnt[j - 1], f[i - 1][j] - C * j);
            for (reg int j = 100 ; j >= 1 ; j --) mnw[j] = min(mnw[j + 1], f[i - 1][j] + C * j);    
            for (reg int j = h[i] ; j <= 100 ; j ++)
                f[i][j] = min(C * j + mnt[j], - C * j + mnw[j]) + (j - h[i]) * (j - h[i]);
        }
        for (reg int i = 1 ; i <= 100 ; i ++) ans = min(ans, f[n][i]);
        cout << ans << endl;
        return 0;
    }
  • 相关阅读:
    IIS6.0服务器架站无法访问解决方案总结
    DNN中做支持多语言的模块
    在dotnetnuke中创建 parent portal
    DNN,Rainbow资源
    2005年岁末,各种主流CMS系统的比较和汇总
    在DNN中获取所有模块信息
    学习dnn的新资源,sooooooooo great!!
    DNN的电子商务模块
    DNN学习笔记
    也学ASP.NET 2.0 AJAX 之二:使用Timer控件
  • 原文地址:https://www.cnblogs.com/BriMon/p/9778530.html
Copyright © 2011-2022 走看看