[bzoj 1096] [ZJOI2007]仓库建设
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[bzoj 1096] [ZJOI2007]仓库建设相关的知识,希望对你有一定的参考价值。
[bzoj 1096] [ZJOI2007]仓库建设
Time Limit: 10 Sec Memory Limit: 162 MB
Submit: 5262 Solved: 2341
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
0 5 10
5 3 100
9 6 10
Sample Output
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。
感觉很好啊~~~
轻松写出转移方程:fi=min{fj+ci+sigma(k=j+1,i)pk*(xi-xk)}(j<i)
设s1i=sigma(j=1,i)pj,s2i=sigma(j=1,i)pj*xj
展开得到fi=fj+ci+s1ixi-s1jxi-s2i+s2j
设k<j且fj优于fk,则有xi>((fj+s2j)-(fk+s2k))/(s1j-s1k)。
然后可以稍微简化一下原式,方便观察分类——
设Ci=ci+s1ixi-s2i,Di=s2i
fi=fj+Ci+Dj-xis1j,这样就方便了处理。
code:(假装是已经掌握了一类斜率DP的真谛)
1 %:pragma GCC optimize(2) 2 #include<bits/stdc++.h> 3 #define sqr(x) ((x)*(x)) 4 #define LL long long 5 using namespace std; 6 const int N=1000005; 7 const double inf=1e18; 8 int n,k,l,r; LL X[N],P[N],C[N],s1[N],s2[N],f[N]; 9 struct point { 10 LL x,y; 11 point() {} 12 point(LL _x,LL _y):x(_x),y(_y) {} 13 }st[N]; 14 int read() { 15 int x=0,f=1; char ch=getchar(); 16 while (ch<‘0‘||ch>‘9‘) f=(ch==‘-‘)?-1:1,ch=getchar(); 17 while (ch>=‘0‘&&ch<=‘9‘) x=x*10+ch-‘0‘,ch=getchar(); 18 return x*f; 19 } 20 double slope(point u,point v) { 21 return u.x==v.x?(u.y<v.y?inf:-inf):1.0*(v.y-u.y)/(v.x-u.x); 22 } 23 LL get(LL k) { 24 while (l<r&&slope(st[l],st[l+1])<1.0*k) l++; 25 return st[l].y-k*st[l].x; 26 } 27 void insert(point cur) { 28 while (l<r&&slope(st[r-1],st[r])>slope(st[r-1],cur)) r--; 29 st[++r]=cur; 30 } 31 int main() { 32 n=read(),s1[0]=s2[0]=0; 33 for (int i=1; i<=n; i++) X[i]=read(),P[i]=read(),C[i]=read(); 34 for (int i=1; i<=n; i++) s1[i]=s1[i-1]+P[i],C[i]+=s1[i]*X[i]; 35 for (int i=1; i<=n; i++) s2[i]=s2[i-1]+P[i]*X[i],C[i]-=s2[i]; 36 l=1,r=0,st[++r]=point(0,0); 37 for (int i=1; i<=n; i++) { 38 f[i]=get(X[i])+C[i]; 39 insert(point(s1[i],f[i]+s2[i])); 40 } 41 printf("%lld\n",f[n]); 42 return 0; 43 }
以上是关于[bzoj 1096] [ZJOI2007]仓库建设的主要内容,如果未能解决你的问题,请参考以下文章
BZOJ_1096_[ZJOI2007]_仓库建设_(斜率优化动态规划+单调队列+特殊的前缀和技巧)