斜率優化\(dp\)是難倒我很久的乙個演算法,我花了很長時間都難以理解。後來,經過無數次的研究加以對一些例題的理解,總算啃下了這根硬骨頭。
斜率優化\(dp\)的式子略有些複雜,大致可以表示成這樣:
\[f_i=min_^(a(j)-b(j)*s(i)+c(i))
\]其中\(a(j)\)和\(b(j)\)是兩個只與\(j\)有關的函式,\(s(i)\)和\(c(i)\)是兩個只與\(i\)有關的函式,式子中的\(min\)其實也可以替換成\(max\),但這裡以\(min\)為例。
不難發現,如果只有\(a(j)\)和\(c(i)\)兩項,就是單調佇列優化\(dp\)
的基本式子了。
但是,由於式子中含有\(b(j)*s(i)\)這一項既與\(i\)相關,又與\(j\)相關的式子,就不能直接用單調佇列,而要進行一定轉化了。
考慮將\(a(j)\)移到等號左邊,並將\(f_i\)移到等號右邊,則原式可以轉化成這樣:
\[a(j)=b(j)*s(i)+(f_i-c(i))
\]注意,在\(i\)不變的時候,我們可以將只與\(i\)有關的項看成常數項。
於是,這個函式就可以看作一條直線,其中\(s(i)\)就相當於這條直線的斜率,而\(f_i-c(i)\)就相當於這條直線的截距。
而\(c(i)\)是固定的,因此,如果要讓\(f_i\)最小,則應讓\(f_i-c(i)\)最小,對應到影象中就是讓截距最小。
那麼應如何讓截距最小呢?
首先,我們可以想象有一條斜率固定的直線(我太懶,不想畫圖... ...),然後圖上有若干個點,現在要用這條直線從圖的最下方往上慢慢移動,直至碰到第乙個點,而這個點就是我們要找的最優點。
則不難發現,如果連續的三個點呈上凸狀,則無論該直線斜率取多少,碰到的第乙個點都不可能是中間這個點。
換句話說,就是中間這個點對答案沒有任何貢獻了。
於是就有乙個策略:當我們要加入乙個新的點時,比較當前點與前乙個插入的點\(s_1\)、前乙個插入的點與倒數第二個插入的點的斜率\(s_2\),如果\(s_1\le s_2\),則可將前乙個插入的點彈出。
重複此操作,直至\(s_1>s_2\)或圖上只剩乙個點,然後將當前點插入。
但是,這樣一來,我們好像還是沒能求出最優解。
此時又有兩種操作方式:在凸包上二分或單調佇列維護最優解。
對於某些問題,它可以確保決策單調性,即乙個點如果當前不是最優解,則以後都不可能是最優解了。這樣的問題可以直接用單調佇列來維護最優解。
但有些問題卻不一定滿足這種性質,此時就需要在凸包上二分最優解了,但依然需要用單調佇列來維護點集。
所以,如果你不會單調佇列,最好趕緊去研究一下,然後再學習斜率優化\(dp\)。
第一道例題:【bzoj2726】[sdoi2012] 任務安排
聽說是入門題?洛谷上的弱化版可以直接單調佇列維護,但是\(bzoj\)上存在負數,需要在凸包上二分。
第二道例題:【cf311b】cats transport
一眼看上去像是\(wqs\)二分,其實題意轉換後可以直接斜率優化。
第三道例題:【洛谷3648】[apio2014] 序列分割
一開始覺得是區間\(dp\),結果一看資料範圍,推了波性質,才發現其實可以用斜率優化\(dp\)來做。
動態規劃 單調斜率優化DP
acwing 1087.修剪草坪 旅行商問題 輸入樣例 641 351 23 輸出樣例 acwing 1087.修剪草坪 動態規劃 f i max f i 1 f i j 1 sum i j sum i f i 表示從前i個中選,且合法的方案數。令x i j,則有 f i min f i 1 f x...
動態規劃 斜率優化
一 引用 一般dp 方程可以轉化成 dp i f j x i 的形式,其中 f j 中儲存了只與 j相關的量。這樣的 dp方程可以用單調佇列進行優化,從而使得 o n 2 的複雜度降到 o n 可是並不是所有的方程都可以轉化成上面的形式,舉個例子 dp i dp j x i x j x i x j ...
斜率優化動態規劃
fi min fj s i2 sj l 2 2 si s j l fi min f j s i2 sj l 2 2si sj l 形如這個式子關於i的項與關於j的項混雜 相乘 的狀態轉移方程,可以使用斜率優化來加速 接下來以優化這個式子為例說說斜率優化.將上方給出的式子去掉 min min,僅關於j...