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

Posted 友人A

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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\n",ans);
    return 0;
}
View Code

 














以上是关于bzoj 1705: [Usaco2007 Nov]Telephone Wire 架设电话线——dp的主要内容,如果未能解决你的问题,请参考以下文章

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

bzoj1640[Usaco2007 Nov]Best Cow Line 队列变换*&&bzoj1692[Usaco2007 Dec]队列变换*

[BZOJ] 1706: [usaco2007 Nov]relays 奶牛接力跑

BZOJ 1707 [Usaco2007 Nov]tanning分配防晒霜

[BZOJ1706][usaco2007 Nov]relays 奶牛接力跑

[BZOJ1642][Usaco2007 Nov]Milking Time 挤奶时间