BZOJ 1096 【ZJOI2007】 仓库建设

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公司寻找一个仓库建设的方案,使得总的费用(建造费用+运输费用)最小。ios

Input

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

Output

  仅包含一个整数,为能够找到最优方案的费用。spa

HINT

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

 

  因而最近我又开始刷BZOJ了……不过以我这水平也只能刷些水题……blog

  又碰到了一个斜率优化dp……如今好像已经有点感受了,反正一维dp超级简单复杂度又不对的题大多数都是斜率优化题。ip

  一维方程你们应该都会……设fi表示在工厂i修仓库的最小费用,每次转移枚举上一个仓库在哪里便可。get

  这个斜率我已经不想推了……原谅我太懒了。网上写的都很好,要看请戳这里。WA了三发由于算斜率时没有开double简直差评……string

  下面贴代码:产品

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
#define maxn 1000010

using namespace std;
typedef long long llg;

struct data{
	llg x,y;
}s[maxn];
int n,X[maxn],C[maxn],d[maxn],l,r;
llg s1[maxn],s2[maxn],f[maxn];

int getint(){
	int w=0;bool q=0;
	char c=getchar();
	while((c>'9'||c<'0')&&c!='-') c=getchar();
	if(c=='-') c=getchar(),q=1;
	while(c>='0'&&c<='9') w=w*10+c-'0',c=getchar();
	return q?-w:w;
}

long double xie(data x,data y){
	if(x.x==y.x) return 1e100;
	return (long double)(y.y-x.y)/(long double)(y.x-x.x);
}

int main(){
	File("a");
	n=getint();
	for(int i=1,P;i<=n;i++){
		X[i]=getint(); P=getint(); C[i]=getint();
		s1[i]=s1[i-1]+P; s2[i]=s2[i-1]+(llg)X[i]*(llg)P;
	}
	for(int i=1;i<=n;i++){
		while(l<r && xie(s[d[l]],s[d[l+1]])<=X[i]) l++;
		f[i]=(llg)C[i]+f[d[l]]+(s1[i]-s1[d[l]])*(llg)X[i]-s2[i]+s2[d[l]];
		s[i].x=s1[i]; s[i].y=f[i]+s2[i];
		while(l<r && xie(s[d[r-1]],s[d[r]])>xie(s[d[r]],s[i])) r--;
		d[++r]=i;
	}
	printf("%lld",f[n]);
}
相关文章
相关标签/搜索