zoukankan      html  css  js  c++  java
  • Bzoj1096 [ZJOI2007]仓库建设

    Time Limit: 10 Sec  Memory Limit: 162 MB
    Submit: 4193  Solved: 1845

    Description

      L公司有N个工厂,由高到底分布在一座山上。如图所示,工厂1在山顶,工厂N在山脚。由于这座山处于高原内
    陆地区(干燥少雨),L公司一般把产品直接堆放在露天,以节省费用。突然有一天,L公司的总裁L先生接到气象
    部门的电话,被告知三天之后将有一场暴雨,于是L先生决定紧急在某些工厂建立一些仓库以免产品被淋坏。由于
    地形的不同,在不同工厂建立仓库的费用可能是不同的。第i个工厂目前已有成品Pi件,在第i个工厂位置建立仓库
    的费用是Ci。对于没有建立仓库的工厂,其产品应被运往其他的仓库进行储藏,而由于L公司产品的对外销售处设
    置在山脚的工厂N,故产品只能往山下运(即只能运往编号更大的工厂的仓库),当然运送产品也是需要费用的,
    假设一件产品运送1个单位距离的费用是1。假设建立的仓库容量都都是足够大的,可以容下所有的产品。你将得到
    以下数据:1:工厂i距离工厂1的距离Xi(其中X1=0);2:工厂i目前已有成品数量Pi;:3:在工厂i建立仓库的费用
    Ci;请你帮助L公司寻找一个仓库建设的方案,使得总的费用(建造费用+运输费用)最小。

    Input

      第一行包含一个整数N,表示工厂的个数。接下来N行每行包含两个整数Xi, Pi, Ci, 意义如题中所述。

    Output

      仅包含一个整数,为可以找到最优方案的费用。

    Sample Input

    3
    0 5 10
    5 3 100
    9 6 10

    Sample Output

    32

    HINT

    在工厂1和工厂3建立仓库,建立费用为10+10=20,运输费用为(9-5)*3 = 12,总费用32。如果仅在工厂3建立仓库,建立费用为10,运输费用为(9-0)*5+(9-5)*3=57,总费用67,不如前者优。

    【数据规模】

    对于100%的数据, N ≤1000000。 所有的Xi, Pi, Ci均在32位带符号整数以内,保证中间计算结果不超过64位带符号整数。 

    斜率优化DP

    如果知道将j+1到i范围的所有产品都运输到i的花费cost(j+1,i),那么f[i]=min{f[j]+cost(j+1,i)}

    cost如何计算?

    sum[i]为p[i]的前缀和

    如果所有物品都从0开始运到i,则费用为(sum[i]-sum[j])*x[i]

    但由于物品的起始点不在0,所以每个物品可以少花费x[i]*p[i]

    b[i]为x[i]*p[i]的前缀和

    ——引自hzwer神犇的博客

    假设有两个断点k,j,(k<j),j比k更优,得到:

      (f[j]+w[j]-f[k]-w[k])/(s[j]-s[k]) < x[i]

      这里w相当于上文b

    (第一遍算的时候符号弄错了,纠结了半天,尴尬)

    维护一个……下凸包?

    上下傻傻分不清楚,看上去求最小值就是斜率尽量小,求最大值就是斜率尽量大

    斜率尽量小,维护的单调队列里斜率就单调递增……

     1 /*by SilverN*/
     2 #include<iostream>
     3 #include<algorithm>
     4 #include<cstring>
     5 #include<cstdio>
     6 #include<cmath>
     7 #define LL long long
     8 using namespace std;
     9 const int mxn=1000010;
    10 int read(){
    11     int x=0,f=1;char ch=getchar();
    12     while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    13     while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
    14     return x*f;
    15 }
    16 int n;
    17 LL x[mxn],p[mxn],c[mxn];
    18 LL smm[mxn];
    19 LL f[mxn],w[mxn];
    20 double gt(int b,int a){
    21     return (double)(f[a]+w[a]-f[b]-w[b])/(smm[a]-smm[b]);
    22 }
    23 int q[mxn],hd,tl;
    24 int main(){
    25     n=read();
    26     int i,j;
    27     for(i=1;i<=n;i++){
    28         x[i]=read();p[i]=read();c[i]=read();
    29         smm[i]=smm[i-1]+p[i];
    30         w[i]=w[i-1]+p[i]*x[i];
    31     }
    32     hd=tl=0;
    33     for(i=1;i<=n;i++){
    34         while(hd<tl && gt(q[hd],q[hd+1])<x[i])hd++;
    35         j=q[hd];
    36         f[i]=f[j]+x[i]*(smm[i]-smm[j])-w[i]+w[j]+c[i];
    37         while(hd<tl && gt(q[tl-1],q[tl])>gt(q[tl],i))tl--;
    38         q[++tl]=i;
    39     }
    40     printf("%lld
    ",f[n]);
    41     return 0;
    42 }
  • 相关阅读:
    1093 Count PAT's(25 分)
    1089 Insert or Merge(25 分)
    1088 Rational Arithmetic(20 分)
    1081 Rational Sum(20 分)
    1069 The Black Hole of Numbers(20 分)
    1059 Prime Factors(25 分)
    1050 String Subtraction (20)
    根据生日计算员工年龄
    动态获取当前日期和时间
    对计数结果进行4舍5入
  • 原文地址:https://www.cnblogs.com/SilverNebula/p/6231410.html
Copyright © 2011-2022 走看看