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]);
}
相關文章
相關標籤/搜索