斜率優化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]表示劃分前i個任務的最小費用。
這樣就寫出了動態規劃方程。
二、簡單題2
將上題的n<=5000改為n<=300000。
Solution
這就是本文的重點所在了。
在上文中的動態規劃中,尚有兩種簡單的優化思路:
- 優化狀態:將這樣一個動態規劃轉化為貪心或數學題。
- 優化轉移:優化轉移的時間(主要為優化重複或不必要的轉移)。
顯然,優化狀態很難達成,那麼我們考慮優化轉移。
我們可以發現在轉移的過程中有很多的不必要的轉移:
考慮一下兩個轉移:
在此題中,若
那麼轉移 j 就是不必要的。
也就是說,若有且選取轉移狀態的集合
並且存在,後面的轉移比前面的優,則前面的轉移就是無意義的,也就是對最終答案無貢獻的了。
考慮本題,如何判斷轉移狀態是否是有用的呢?
也就是說,如果
那麼後面的轉移比前面的優,否則前面的轉移比後面的優。
這樣的,即是用斜率的形式,表現了轉移之間的不必要的關係。
進一步,我們發現:
也就是說,如果當前存在後面的轉移比前面的優,那麼這個轉移在之後的狀態中都不會成為最有轉移!
根據這個性質,我們選擇用單調佇列維護一個兩點間斜率單調遞增的點集佇列。
設:
- 若有 ,則的轉移必然不會是最優的,於是能夠將它刪除。(維護隊尾)
- 若有, 則x1的轉移必然不會是最優的,於是能夠將它刪除。 (維護隊首)
最後的點集佇列滿足:在隊首的點的轉移必然是最優的。
於是
將轉移化為,動態規劃完成。
三、簡單題3
若 -512<=t[i]<=512 ,也就是說:
不再成立怎麼辦呢?
我們發現:
- 若有 ,則的轉移必然不會是最優的,於是能夠將它刪除。(維護隊尾)
這一性質依然成立,那麼這個點集集合還是會組成一個相鄰點斜率遞增的單調佇列。
有
發現:
- 如果,那麼優於。
- 如果,那麼優於。
也就是說,答案一定存在於一個點,使得 且
那麼必然最優。
我們可以維護單調佇列,只在隊尾刪除,每次二分查詢一個最優點。
這樣便是的斜率優化做法。
四、簡單題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維護斜率凸包解決斜率優化問題了。
下次有時間再補充。。。