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

    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。


    分析:

    一般的DP:设f[i][j]表示前i根电线杆高度为j的最小花费。

    f[i][j]=min{f[i-1][k]+(k-a[i])^2+c*abs(j-k)。显然会T。

    考虑优化这个方程,我们把绝对值打开。

    if(k<=j) f[i][j]=f[i-1][k]-c*k+c*j+(k-a[i])^2

    else f[i][j]=f[i-1][k]+c*k-c*j+(k-a[i])^2

    f[i-1][k]-c*k和f[i-1][k]+c*k的最小值可以在求出f的时候同时更新。

    代码:

    #include <stdio.h>
    #include <string.h>
    #include <algorithm>
    using namespace std;
    #define N 100050
    #define mem(x) memset(x,0x3f,sizeof(x))
    int f[N], n, a[N], l[120], r[120], m, c;
    int main() {
    	scanf("%d%d", &n, &c);
    	int i, j;
    	for(i = 1;i <= n; ++ i) scanf("%d",&a[i]), m = max(m, a[i]);
    	memset(f, 0x3f, sizeof(f));
    	for(i = a[1];i <= m; ++ i) f[i] = (i - a[1]) * (i - a[1]);
    	for(i = 2;i <= n; ++ i) {
    		mem(l);
    		mem(r);
    		for(j = a[i - 1];j <= m; ++ j) {
    			l[j] = min(l[j - 1], f[j] - c * j);
    		}
    		for(j = m;j >= a[i - 1]; -- j) {
    			r[j] = min(r[j + 1], f[j] + c * j);
    		}
    		for(j = a[i - 1] - 1;j >= 1; -- j) {
    			r[j] = r[j + 1];
    		}
    		for(j = a[i];j <= m; ++ j) {
    			f[j] = (j - a[i]) * (j - a[i]) + min(l[j] + c * j, r[j] - c * j);
    		}
    	}
    	int ans = 1<<30;
    	for(i = a[n];i <= m; ++ i) ans = min(ans, f[i]);
    	printf("%d
    ",ans);
    }
    
  • 相关阅读:
    MySQL与SQLServer的update left join语法区别
    request获取真实IP
    request获取前台表单
    ehcache memcache redis 三大缓存
    StraUML简单教程
    JSP模板
    判断是否为同一天
    eneityManager的merge、Flush、Refresh方法
    javascript
    javax.naming.NameNotFoundException:Name[ XXX] is not bound in this context.
  • 原文地址:https://www.cnblogs.com/suika/p/8678110.html
Copyright © 2011-2022 走看看