斜率優化dp小結

2021-08-08 18:43:12 字數 1385 閱讀 9946

先推薦一篇部落格

下文有小部分修改自:

有些dp方程可以轉化成dp[i]=f(i,j)+x[i]的形式,其中f[j]與i和j有關。這樣的dp方程無法直接使用單調佇列進行優化,所以考慮另外一中降低複雜度的方式:斜率優化!

舉個例題:hdu 3507

設dp[i]表示到i的最少花費,sum[i]表示從a[1]到a[i]的數字和,有dp[i]=dp[j]+(sum[i]-sum[j])^2+m。假設k < j < i。如果在j的時候決策要比在k的時候決策好,即

dp[j]+m+(sum[i]-sum[j])^2 < dp[k]+m+(sum[i]-sum[k])^2。(求最小花費,所以優就是小於)

上不等式可以表示成yj-yk/xj-xk < sum[i],左邊就是斜率g(j,k)的表示。

以下是核心操作:

假設k < j < i並且g(i,j) < g(j,k)那麼j一定不屬於此題(優表示小於的情況)最優解集。

①若g(i,j) < sum[p],那麼顯然i比j優,排除j

②若g(i,j) ≥ sum[p],那麼j比i優,但是有一前提成立g(j,k) > g(i,j),所以g(j,k) > sum[p],所以k比j優,j也可以排除。

於是成功地排除了無效點,維護了乙個下凸的圖形

下圖中左邊為有效點集,右邊為存在無效點的集合

具體**實現:

定義乙個單調佇列。

①移動隊首,找到乙個斜率最大的合法的g(h+1,h),即右移到最後乙個g(h+1,h)。

②用隊首更新當前點(dp陣列賦值)

③不斷左移隊尾,剔除不合法的點集。

下面是hdu 3507的ac**:

/*

dp[i]=dp[j]+m+(sum[i]-sum[j])^2

(dp[j]+sum[j]^2-(dp[k]+sum[k]^2))/(2

*(sum[j]-sum[k]))*/

#include

#include

#include

#include

using namespace std;

const int maxn=500002;

int n,m;

int sum[maxn],dp[maxn],q[maxn];

inline int gety(int

x,int

y) inline int getx(int

x,int

y) int main()

printf("%d\n",dp[n]);

}return

0;}

斜率優化dp小結

在寫斜率優化之前,我們來回顧一下單調佇列優化的dp 1.對於如下形式的dp方程 dp i min 0 j我們直接用乙個變數維護 0,i 中dp j f j 的最小值即可 2.對於如下形式的dp方程 dp i min i m j我們可以用乙個單調佇列維護乙個 i m,j 中dp j f j 的最小值,...

斜率優化dp小結

最近刷了幾道斜率優化dp算是對斜率優化有了一定的了解了 現在來小結一下 斜率優化dp的優化能力是將n 2優化成n,n 3優化成n 2 其轉移方程一般是dp k min dp i cost i 1 k 斜率優化優化的是排除一些不可能是最優解的解,那麼什麼情況下不可能是最優解呢 下面看一道題hdu 28...

斜率優化dp小結

在寫斜率優化之前,我們來回顧一下單調佇列優化的dp 1.對於如下形式的dp方程 dp i min 0 我們直接用乙個變數維護 0,i 中dp j f j 的最小值即可 2.對於如下形式的dp方程 dp i min i m 我們可以用乙個單調佇列維護乙個 i m,j 中dp j f j 的最小值,然後...