[題目描述]
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;
[題解]這道題很坑爹,裸的dp方程都讓我推了好久.
顯然,f[i]=c[i]+min(f[j]+sigma(p[k]*d[k]))(k>j且k<=i)(爲了接下來運算的方便,將i也包括進來)(d[i],即爲題目中的xi,爲了不與下面的x重複,用d代替)
令s1[i]=sigma(p[k]x[k]),k<=i;s2=sigma(p[k]),k<=i
f[i]=min(f[j]+x[i]*(s2[i]-s2[j])-(s1[i]-s1[j]))+c[i]
經過一系列轉化,我們得到:f[i]=min(f[j]+s1[j]-d[i]s2[j])+d[i]s2[i]-s1[i]+c[i].
到這裏,剩下的就很簡單了.我Wa了若干次,原因一個是因爲單調性搞錯,導致凸殼的方向搞錯,另一個是因爲沒有將f[0]加入單調隊列(坑爹啊),最後一個是因爲將除法移項時沒注意移的項的正負性而沒有變號.
Code
program storage;
type int=int64;real=extended;
var
i,j:longint;
l,r,n:longint;
d,p,c,x,y,s1,s2,f:array[0..1000000]of real;
k,a,b:real;
begin
assign(input,'storage.in');reset(input);
assign(output,'storage.out');rewrite(output);
read(n);s1[0]:=0;s2[0]:=0;
for i:=1 to n do begin
read(d[i],p[i],c[i]);
s1[i]:=s1[i-1]+p[i]*d[i];
s2[i]:=s2[i-1]+p[i];
end;
l:=1;r:=1;f[0]:=0;x[0]:=0;y[0]:=0;
for i:=1 to n do begin
while(l<r)and((y[l]-y[l+1])>(x[l]-x[l+1])*d[i])do inc(l);
f[i]:=c[i]-s1[i]+d[i]*s2[i]+y[l]-d[i]*x[l];
a:=s2[i];b:=f[i]+s1[i];
while(l<r)and((y[r]-y[r-1])*(a-x[r])>(x[r]-x[r-1])*(b-y[r]))do dec(r);
inc(r);x[r]:=a;y[r]:=b;
end;
write(f[n]:0:0);
close(input);close(output);
end.
BY QW
轉載請註明出處