[BZOJ1096] [ZJOI2007] 仓库建设 (斜率优化dp)

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位带符号整数。

Source

Solution

  设$f[i]$表示在第$i$个工厂建仓库时前$i$个工厂的最小花费,则:

  $\displaystyle f[i]=min\left\{f[j]+\sum_{k=j+1}^{i}(c[i]-c[k])*p[k]\right\}+c[i]$

    $\displaystyle=min\left\{f[j]+c[i]*\sum_{k=j+1}^{i}p[k]-\sum_{k=j+1}^{i}c[k]*p[k]\right\}+c[i]$

  令$\displaystyle sump[i]=\sum_{j=1}^i p[j]$,$\displaystyle sumxp[i]=\sum_{j=1}^i x[j]*p[j]$,则:

  $\displaystyle f[i]=min\big\{\ f[j]+x[i]*(sump[i]-sump[j])-(sumxp[i]-sumxp[j])\ \big\}+c[i]$

  据说$f[i]$满足决策单调性,辣么这一步的证明跳过= =b

  设$j<k$且$k$比$j$优,那么最后化成的斜率式是这样的:$\displaystyle\frac{(f[k]+sumxp[k])-(f[j]+sumxp[j])}{sump[k]-sump[j]}<c[i]$

  维护下凸壳搞一搞就行了

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 int x[1000005], p[1000005], c[1000005], q[1000005];
 5 ll sump[1000005], sumxp[1000005], f[1000005];
 6
 7 double slope(int i)
 8 {
 9     return 1.0 * (f[q[i]] + sumxp[q[i]] - f[q[i - 1]] - sumxp[q[i - 1]]) / (sump[q[i]] - sump[q[i - 1]]);
10 }
11
12 int main()
13 {
14     int n, front = 0, back = 1;
15     scanf("%d", &n);
16     for(int i = 1; i <= n; ++i)
17     {
18         scanf("%d%d%d", x + i, p + i, c + i);
19         sump[i] = sump[i - 1] + p[i];
20         sumxp[i] = sumxp[i - 1] + (ll)x[i] * p[i];
21     }
22     for(int i = 1; i <= n; ++i)
23     {
24         while(front < back - 1 && slope(front + 2) < x[i])
25             ++front;
26         int j = q[front + 1];
27         f[i] = f[j] + x[i] * (sump[i] - sump[j]) - sumxp[i] + sumxp[j] + c[i];
28         q[++back] = i;
29         while(front < back - 2 && slope(back) < slope(back - 1))
30             q[--back] = i;
31     }
32     printf("%lld\n", f[n]);
33     return 0;
34 }

时间: 2024-10-11 12:02:56

[BZOJ1096] [ZJOI2007] 仓库建设 (斜率优化dp)的相关文章

bzoj-1096 1096: [ZJOI2007]仓库建设(斜率优化dp)

题目链接: 1096: [ZJOI2007]仓库建设 Description L公司有N个工厂,由高到底分布在一座山上.如图所示,工厂1在山顶,工厂N在山脚.由于这座山处于高原内陆地区(干燥少雨),L公司一般把产品直接堆放在露天,以节省费用.突然有一天,L公司的总裁L先生接到气象部门的电话,被告知三天之后将有一场暴雨,于是L先生决定紧急在某些工厂建立一些仓库以免产品被淋坏.由于地形的不同,在不同工厂建立仓库的费用可能是不同的.第i个工厂目前已有成品Pi件,在第i个工厂位置建立仓库的费用是Ci.对

BZOJ 1096 [ZJOI2007]仓库建设 斜率优化dp

1096: [ZJOI2007]仓库建设 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/problem.php?id=1096 Description L公司有N个工厂,由高到底分布在一座山上.如图所示,工厂1在山顶,工厂N在山脚. 由于这座山处于高原内陆地区(干燥少雨),L公司一般把产品直接堆放在露天,以节省费用.突然有一天,L公司的总裁L先生接到气象部门的电话,被告知三天之后将有一场

【BZOJ-1096】仓库建设 斜率优化DP

1096: [ZJOI2007]仓库建设 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 3719  Solved: 1633[Submit][Status][Discuss] Description L公司有N个工厂,由高到底分布在一座山上.如图所示,工厂1在山顶,工厂N在山脚.由于这座山处于高原内陆地区(干燥少雨),L公司一般把产品直接堆放在露天,以节省费用.突然有一天,L公司的总裁L先生接到气象部门的电话,被告知三天之后将有一场暴雨,于是L先

P2120 [ZJOI2007]仓库建设 斜率优化dp

好题,这题是我理解的第一道斜率优化dp,自然要写一发题解.首先我们要写出普通的表达式,然后先用前缀和优化.然后呢?我们观察发现,x[i]是递增,而我们发现的斜率也是需要是递增的,然后就维护一个单调递增就行了. 放一个证明题解. 设f[i]表示在i点建仓库的最小费用,易得方程:f[i]=min(f[j]+(x[i]-x[j+1])*p[j+1]+(x[i]-x[j+1])*p[j+2]...) =min(f[j]+c[i]+x[i]*(p[j+1..i])-(x[j+1]*p[j+1]+...+x

[Bzoj1096][ZJOI2007]仓库建设(斜率优化)

题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1096 一开始想了想费用流,然后被数据范围pass掉了,感觉dp更可行一些. 只想到一个O(n2)的做法,看到式子比较复杂,就感觉像是斜率优化. dp[i]表示前i个工厂所求的最小费用,则第i个工厂一定会建一个仓库.转移方程为$dp[i]=min(dp[j]+\sum_{k=j}^{i-1}p[k]*(x[i]-x[k]))+c[i]$. 将式子展开,用sump表示p数组的前缀和,sum

【bzoj1096】仓库建设——斜率优化dp

题目链接 我们用sum[i]表示前i个工厂的产品数之和,b[i]表示x[i]*p[i]的前缀和,因此第j+1~i个工厂的产品运到第i个工厂的代价就是 (sum[i]-sum[j])*x[i]-(b[i]-b[j])+ci[i] 最后f[i]的状态转移方程即为: f[i]=f[j]+(sum[i]-sum[j])*xi[i]-(b[i]-b[j])+ci[i] 斜率式的推导过程就不写了,最后可以化成: (f[j]+b[j]-f[k]-b[k])/(sum[j]-sum[k])<xi[i]-ci[i

BZOJ 1096 ZJOI2007 仓库设计 斜率优化dp

太高兴了,这是我第一次自己独立思考的斜率优化dp,从头到尾都是自己想的.(相信自己,能行的,不过也做了40分钟了). 这道题目还好吧! 看到之后第一反应是想设从工厂0运到工厂i 总共需要 tot[i] 的费用, 用 p[i] 表示从山顶到工厂 i 总共的产品数, 再用 x[i] 表示从工厂0到工厂 i 的距离, 那么状态转移方程就是 f[i] = min{f[j] + tot[i] - tot[j] - p[j] * (x[i] - x[j] ) + c[i] } ,很明显由于数据有 n <=

[ZJOI2007]仓库建设(斜率优化)

L公司有N个工厂,由高到底分布在一座山上. 工厂1在山顶,工厂N在山脚. 由于这座山处于高原内陆地区(干燥少雨),L公司一般把产品直接堆放在露天,以节省费用. 突然有一天,L公司的总裁L先生接到气象部门的电话,被告知三天之后将有一场暴雨,于是L先生决定紧急在某些工厂建立一些仓库以免产品被淋坏. 由于地形的不同,在不同工厂建立仓库的费用可能是不同的.第i个工厂目前已有成品Pi件,在第i个工厂位置建立仓库的费用是Ci. 对于没有建立仓库的工厂,其产品应被运往其他的仓库进行储藏,而由于L公司产品的对外

BZOJ 1096 ZJOI2007 仓库建设 斜率优化

题目大意:给定n个厂房,在其中一些建仓库,一个点如果没有仓库就要把仓库运到右侧的仓库中,求最小花销 很简单的斜率优化--之前刷斜率优化的时候怎么居然把这道题漏了 令f[i]为在i点建厂使i之前的货物全部安置的最小花销 则有 公式编辑器就是爽啊~ 令sump[i]为p[i]的前缀和 令sumxp[i]为p[i]*x[i]的前缀和 化简有 f[j] + sumxp[j] = x[i]*sump[j] + sumxp[i] - x[i]*sump[i] - C[i] + f[i] 其中 X[j]=su