1. 程式人生 > >斜率優化Convex Hull Trick

斜率優化Convex Hull Trick

斜率優化

一、簡單DP

首先從一道簡單題引入。

[IOI2002]任務安排

Description

N個任務排成一個序列在一臺機器上等待完成(順序不得改變),這N個任務被分成若干批,每批包含相鄰的若干任務。從時刻0開始,這些任務被分批加工,第i個任務單獨完成所需的時間是Ti。在每批任務開始前,機器需要啟動時間S,而完成這批任務所需的時間是各個任務需要時間的總和(同一批任務將在同一時刻完成)。每個任務的費用是它的完成時刻乘以一個費用係數ci。請確定一個分組方案,使得總費用最小。

例如:S=1;T={1,3,4,2,1};F={3,2,3,3,4}。如果分組方案是{1,2}、{3}、{4,5},則完成時間分別為{5,5,10,14,14},費用C={15,10,30,42,56},總費用就是153。

Input

第一行是N(1<=N<=5000)。

第二行是S(0<=S<=50)。

下面N行每行有一對數,分別為Ti和ci,均為不大於100的正整數,表示第i個任務單獨完成所需的時間是Ti及其費用係數ci。

Output

一個數,最小的總費用。

Sample Input

5

1

1 3

3 2

4 3

2 3

1 4

Sample Output

153

Solution

“光著身子”的動態規劃。

設F[i,j]表示劃分前i個任務為j批的最小費用。

F[i,j]=min(F[k,j-1]+(s*j+\sum_{q=k+1}^{i}t[q] ))*(\sum_{q=k+1}^{i}c[q]))

設T[i]=\sum_{j=1}^{i}t[j]                 C[i]=\sum_{j=1}^{i}c[i]

F[i,j]=min(F[k,j-1]+(s*j+T[i]-T[k] ))*(C[i]-C[k]))

(2D/1D),時間複雜度:O(n^3),空間複雜度:O(n^2)

這顯然是不夠的。

 

實際上我們不一定要知道之前劃分了多少批任務,只需要記錄F[i]表示劃分前i個任務的最小費用。

F[i]=min(F[j]+(s+T[i])*(C[i]-C[j]))+s*(C[i]-C[j])

這樣就寫出了(1D/1D)動態規劃方程。

二、簡單題2

將上題的n<=5000改為n<=300000。

Solution

這就是本文的重點所在了。

在上文中的(1D/1D)動態規劃中,尚有兩種簡單的優化思路:

  1. 優化狀態:將這樣一個動態規劃轉化為貪心或數學題。
  2. 優化轉移:優化轉移的時間(主要為優化重複或不必要的轉移)。

顯然,優化狀態很難達成,那麼我們考慮優化轉移。

我們可以發現在轉移的過程中有很多的不必要的轉移:

考慮一下兩個轉移:

F[i]=min(F[j]+(s+T[i])*(C[i]-C[j]))+s*(C[i]-C[j])

F[i]=min(F[k]+(s+T[i])*(C[i]-C[k]))+s*(C[i]-C[k])

(j<k<i)

在此題中,若 min(F[j]+(s+T[i])*(C[i]-C[j]))\geqslant min(F[k]+(s+T[i])*(C[i]-C[k]))

那麼轉移 j 就是不必要的。

也就是說,若有(i'>i)且選取轉移狀態的集合\begin{Bmatrix} i':& j1, &j2, &... &j\alpha \end{Bmatrix}\subseteq \begin{Bmatrix} i:& j1, &j2, &... &j\beta \end{Bmatrix}

並且存在,後面的轉移比前面的優,則前面的轉移就是無意義的,也就是對最終答案無貢獻的了。

 

考慮本題,如何判斷轉移狀態是否是有用的呢?

F[j]+(s+T[i])*(C[i]-C[j])\geqslant F[k]+(s+T[i])*(C[i]-C[k])

\therefore F[j]-s*c[j]-T[i]*c[j]\geqslant F[k]-s*c[k]-T[i]*c[k]

\therefore F[j]-f[k]+s*(c[k]-c[j])\geqslant T[i]*(c[j]-c[k])

\therefore \frac{F[j]-f[k]+s*(c[k]-c[j]))}{(c[j]-c[k]) }\leqslant T[i]

也就是說,如果 \small \frac{F[j]-f[k]+s*(c[k]-c[j]))}{(c[j]-c[k]) }\leqslant T[i]

那麼後面的轉移比前面的優,否則前面的轉移比後面的優。

這樣的\small \frac{F[j]-f[k]+s*(c[k]-c[j]))}{(c[j]-c[k]) },即是用斜率的形式,表現了轉移之間的不必要的關係。

 

進一步,我們發現:

\small \frac{F[j]-f[k]+s*(c[k]-c[j]))}{(c[j]-c[k]) }\leqslant T[i]\leqslant T[i+1]

也就是說,如果當前存在後面的轉移比前面的優,那麼這個轉移在之後的狀態中都不會成為最有轉移!

根據這個性質,我們選擇用單調佇列維護一個兩點間斜率單調遞增的點集佇列。

設:

\small g(x1,x2)=\frac{F[x1]-f[x2]+s*(c[x2]-c[x1]))}{(c[x1]-c[x2]) }

  1. 若有  \small g(x1,x2)\geqslant g(x2,x3),則\small x2的轉移必然不會是最優的,於是能夠將它刪除。(維護隊尾)
  2. 若有\small g(x1,x2)<=T[i],        則x1的轉移必然不會是最優的,於是能夠將它刪除。 (維護隊首)

最後的點集佇列滿足:在隊首的點的轉移必然是最優的。

於是\small F[i]=F[que[head]]+(s+T[i])*(C[i]-C[que[head]])+s*(C[i]-C[que[head]])

將轉移化為O(1)(1D/0D)動態規劃完成。

三、簡單題3

若   -512<=t[i]<=512 ,也就是說:

\small T[i]\leqslant T[i+1]    不再成立怎麼辦呢?

我們發現:

  1. 若有  \small g(x1,x2)\geqslant g(x2,x3),則\small x2的轉移必然不會是最優的,於是能夠將它刪除。(維護隊尾)

這一性質依然成立,那麼這個點集集合還是會組成一個相鄰點斜率遞增的單調佇列。

\small g(x1,x2)\leqslant g(x2,x3)...\leqslant g(x\alpha ,x\alpha+1 )<=T[i]<=g()...   

發現:

  1. 如果\small g(x\alpha ,x\alpha+1 )< T[i],那麼\small x\alpha +1優於\small x\alpha
  2. 如果\small g(x\alpha ,x\alpha+1 )> T[i],那麼\small x\alpha優於\small x\alpha +1

也就是說,答案一定存在於一個點\small x\alpha,使得g(x\alpha-1,x\alpha ) \leqslant T[i] 且 g(x\alpha,x\alpha +1) \geqslant T[i]

那麼\small x\alpha必然最優。

我們可以維護單調佇列,只在隊尾刪除,每次二分查詢一個最優點。

這樣便是O(nlgn)的斜率優化做法。

 

四、簡單題4

一種形式斜率優化的形式:

佇列中的點不滿足單調性。

BZOJ1492: [NOI2007]貨幣兌換Cash

Description

小Y最近在一家金券交易所工作。該金券交易所只發行交易兩種金券:A紀念券(以下簡稱A券)和 B紀念券(以下

簡稱B券)。每個持有金券的顧客都有一個自己的帳戶。金券的數目可以是一個實數。每天隨著市場的起伏波動,

兩種金券都有自己當時的價值,即每一單位金券當天可以兌換的人民幣數目。我們記錄第 K 天中 A券 和 B券 的

價值分別為 AK 和 BK(元/單位金券)。為了方便顧客,金券交易所提供了一種非常方便的交易方式:比例交易法

。比例交易法分為兩個方面:(a)賣出金券:顧客提供一個 [0,100] 內的實數 OP 作為賣出比例,其意義為:將

 OP% 的 A券和 OP% 的 B券 以當時的價值兌換為人民幣;(b)買入金券:顧客支付 IP 元人民幣,交易所將會兌

換給使用者總價值為 IP 的金券,並且,滿足提供給顧客的A券和B券的比例在第 K 天恰好為 RateK;例如,假定接

下來 3 天內的 Ak、Bk、RateK 的變化分別為:

假定在第一天時,使用者手中有 100元 人民幣但是沒有任何金券。使用者可以執行以下的操作:

注意到,同一天內可以進行多次操作。小Y是一個很有經濟頭腦的員工,通過較長時間的運作和行情測算,他已經

知道了未來N天內的A券和B券的價值以及Rate。他還希望能夠計算出來,如果開始時擁有S元錢,那麼N天后最多能

夠獲得多少元錢。

Input

輸入第一行兩個正整數N、S,分別表示小Y能預知的天數以及初始時擁有的錢數。接下來N行,第K行三個實數AK、B

K、RateK,意義如題目中所述。對於100%的測試資料,滿足:0<AK≤10;0<BK≤10;0<RateK≤100;MaxProfit≤1

0^9。

【提示】

1.輸入檔案可能很大,請採用快速的讀入方式。

2.必然存在一種最優的買賣方案滿足:

每次買進操作使用完所有的人民幣;

每次賣出操作賣出所有的金券。

Output

只有一個實數MaxProfit,表示第N天的操作結束時能夠獲得的最大的金錢數目。答案保留3位小數。

Sample Input

3 100
1 1 1
1 2 2
2 2 3

Sample Output

225.000

 

這一題就是典型的例子。

斜率不單調,那麼就必須用cdq分治或splay維護斜率凸包解決斜率優化問題了。

下次有時間再補充。。。