• [BZOJ1096][ZJOI2007]仓库建设 斜率优化


    1096: [ZJOI2007]仓库建设

    Time Limit: 10 Sec  Memory Limit: 162 MB
    Submit: 4996  Solved: 2230
    [Submit][Status][Discuss]

    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。

    设f[i]表示在i建立仓库的最小费用,s[i]表示前i个工厂的产品数总和,t[i]表示到i为止,每个工厂的货物从1号工厂运到其原来的工厂的花费和。

    则将j+1到i号工厂的货物全部运到i号工厂的花费为(s[i]-s[j])*x[i]-(t[i]-t[j])。

    因此我们得到转移方程:f[i]=min(f[j]+(s[i]-s[j])*x[i]-(t[i]-t[j])+c[i]

    这是考虑斜率优化,

    设j>k,则当f[j]-f[k]+t[j]-t[k]<(s[j]-s[k])*x[i]时j比k优。

    运用单调队列维护即可。

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #include<algorithm>
     5 #include<cstdlib>
     6 #include<cmath>
     7 using namespace std;
     8 int n;
     9 long long d[1000001],w[1000001],c[1000001];
    10 long long f[1000001];
    11 long long s[1000001],t[1000001];
    12 int q[1000001];
    13 int head,tail;
    14 long long up(int k,int j){return f[j]-f[k]+t[j]-t[k];}
    15 long long down(int k,int j){return s[j]-s[k];}
    16 int main()
    17 {
    18     scanf("%d",&n);
    19     for(int i=1;i<=n;i++)
    20     {
    21         scanf("%lld%lld%lld",&d[i],&w[i],&c[i]);
    22         s[i]=s[i-1]+w[i];
    23         t[i]=t[i-1]+w[i]*d[i];
    24     }
    25     for(int i=1;i<=n;i++)
    26     {
    27         while(head<tail&&up(q[head],q[head+1])<down(q[head],q[head+1])*d[i])head++;
    28         int now=q[head];
    29         f[i]=f[now]+(s[i]-s[now])*d[i]-(t[i]-t[now])+c[i];
    30         while(head<tail&&up(q[tail-1],q[tail])*down(q[tail],i)>up(q[tail],i)*down(q[tail-1],q[tail])) tail--;
    31         q[++tail]=i;
    32     }
    33     cout<<f[n];
    34 }
    View Code
    O(∩_∩)O~ (*^__^*) 嘻嘻…… O(∩_∩)O哈哈~
  • 相关阅读:
    Using AlloyTouch to control three.js 3D model
    AlloyTouch与three.js 3D模型交互
    移动Web触摸与运动解决方案AlloyTouch开源啦
    transformjs玩转星球
    swing with transformjs
    和transformjs一起摇摆
    getting started with transformjs
    移动Web利器transformjs入门
    腾讯AlloyTeam移动Web裁剪组件AlloyCrop正式开源
    Why AlloyFinger is so much smaller than hammerjs?
  • 原文地址:https://www.cnblogs.com/wls001/p/7338959.html
Copyright © 2020-2023  润新知