BZOJ1096 [ZJOI2007]倉庫建設


本文版權歸ljh2000和博客園共有,歡迎轉載,但須保留此聲明,並給出原文鏈接,謝謝合作。

  

本文作者:ljh2000
作者博客:http://www.cnblogs.com/ljh2000-jump/
轉載請注明出處,侵權必究,保留最終解釋權!

 

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+斜率優化
解題報告:
  上午校內自測考我的題目,我就可以在機房里面刷題,嘿嘿嘿。
  開始沒看到只能往編號大的運輸這個條件,結果一直沒想出來朴素DP怎么寫...
  朴素的式子就是:$${f[i]=min(f[j]+Xi*{\sum_{k=j+1}^{i}P[k]} - \sum_{k=j+1}^{i}Xk*Pk } )+ Ci$$
  這是n^2的做法,還是那句話,斜率優化的DP式子長得就是一副很可推的樣子,不妨設$${Si=\sum_{k=1}^{i}X[k]*P[k]}$$
  $${SPi=\sum_{k=1}^{i}P[k]}$$
  那么式子變成了: $${f[i]=min(f[j]+Xi*(SPi-SPj)- (Si-Sj) )+ Ci}$$
  假設存在k<j,且j的決策比k優,即
   $${ (f[j]+Xi*(SPi-SPj)- (Si-Sj) )+ Ci  <  (f[k]+Xi*(SPi-SPk)- (Si-Sk) )+ Ci  }$$
  化簡可知:$${f[j]-f[k]+Sj-Sk < Xi*(SPj-SPk) }$$
  把右邊除過去,就會發現
  $${ \frac{f[j]-f[k]+Sj-Sk}{SPj-SPk} < Xi }$$
  哇,這和昨天做的題目好像啊!這就是一個斜率式嘛
  單調隊列維護斜率單增的下凸包,發現隊首不滿足上式了就pop掉,隊尾不滿足同樣pop。
 
 1 //It is made by ljh2000
 2 #include <iostream>
 3 #include <cstdlib>
 4 #include <cstring>
 5 #include <cstdio>
 6 #include <cmath>
 7 #include <algorithm>
 8 #include <ctime>
 9 #include <vector>
10 #include <queue>
11 #include <map>
12 #include <set>
13 using namespace std;
14 typedef long long LL;
15 const int inf = (1<<30);
16 const int MAXN = 1000011;
17 int n,head,tail;
18 int X[MAXN],P[MAXN],C[MAXN],dui[MAXN];
19 LL f[MAXN],s[MAXN],sp[MAXN];
20 
21 inline int getint()
22 {
23     int w=0,q=0; char c=getchar();
24     while((c<'0' || c>'9') && c!='-') c=getchar(); if(c=='-') q=1,c=getchar(); 
25     while (c>='0' && c<='9') w=w*10+c-'0', c=getchar(); return q ? -w : w;
26 }
27 inline LL count(int x,int y){  return ( (f[x]-f[y])+(s[x]-s[y]) ) / (sp[x]-sp[y]) ; }
28 inline void work(){
29     n=getint(); for(int i=1;i<=n;i++) X[i]=getint(),P[i]=getint(),C[i]=getint(),s[i]=s[i-1]+(LL)X[i]*P[i],sp[i]=sp[i-1]+P[i];
30     dui[head=tail=1]=0; int from;
31     for(int i=1;i<=n;i++) {
32     while(head<tail && count(dui[head+1],dui[head])<X[i]) head++;
33     from=dui[head]; f[i]=(LL)f[from]+X[i]*(sp[i]-sp[from])-(s[i]-s[from])+C[i];
34     while(head<tail && count(dui[tail],dui[tail-1])>count(i,dui[tail])) tail--;
35     dui[++tail]=i;
36     }
37     printf("%lld",f[n]);
38 }
39 
40 int main()
41 {
42     work();
43     return 0;
44 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM