[斜率優化的dp]storage題解

[題目描述]

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

轉載請註明出處

發佈了45 篇原創文章 · 獲贊 5 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章