斜率優化DP學習筆記

2022-05-07 01:03:07 字數 2738 閱讀 3502

本文以luogup3195 玩具裝箱為例,我們很容易可以的出下面這個柿子:

\[f_i = \min_^ \

\]設 \(b_i = s_i + i\),\(j\) 為 \(f_i\) 的最優決策點,則有:

\[f_i = f_j + (b_i - b_j - (l + 1)) ^ 2

\]把只與 \(j\) 有關的放在左邊:

\[f_j + b_j + 2 b_j (l + 1) = 2 b_i b_j - b_i ^ 2 - (l + 1) ^ 2 + 2 b_i (l + 1) + f_i

\]把 \(b_j\) 看做橫座標,\(f_j + b_j + 2 b_j (l + 1)\) 看做縱座標,這個式子就是一條經過點 \(\big( b_j, f_j + b_j + 2 b_j (l + 1) \big)\),斜率為 \(2 b_i\) 的直線,\(-b_i^2 - (l + 1) ^ 2 + 2 b_i (l + 1) + f_i\) 就看做截距。

由於 \(b_i\) 是確定的,截距中除 \(f_i\) 以外的所有單項式都是常量,所以 \(j\) 是使該直線截距最小的點,可以看成一條斜率為 \(2 b_i\) 的直線從 \(-\infty\) 上移過程中碰到的第乙個點。

可以維護乙個下凸殼,使直線碰到的第乙個點一定在凸殼上。

上圖中,決策點的下凸殼為 \((b,c,e)\),但因為加入了點 \(g\),點 \(e\) 死了(大霧。

可以得到如下結論:

1、凸殼上邊的斜率是從左到右單調遞增的,否則會出現上圖的情況。

2、設凸殼上的點從左至右依次記為 \(1\)~\(k\),顯然有:在凸殼中加入乙個橫座標大於當前所有點的點 \(t\),若 \(slope (k - 1, t) \leq slope (k - 1, k)\),則 \(k\) 不在凸殼上。

依照上述做法可以用單調棧來維護凸殼。

對於斜率為 \(k\) 的直線,第乙個碰到的點為凸殼上第一條斜率小於 \(k\) 的線段右端點,若沒有則為最左邊的點。

例題中,由於 \(2 b_i\) 的單調性,可以直接用單調佇列把不符合上述條件的點扔掉。

例題是斜率優化的入門題,當做橫座標和斜率的變數都有單調性,所以很好處理,在更加樸素的情況可以大致分為以下兩種:

1、橫座標單調,斜率不單調:不用單調佇列,在單調棧上二分即可,或者也可以打平衡樹;

2、兩者都不單調:我也沒寫過,平衡樹維護應該問題不大。

noi2019d1t1 回家路線

記 \(f_i\) 表示乘坐第 \(i\) 班列車到達站點的最小代價。

暴力轉移是顯然的。

可以把 第\(i\) 班列車看作兩個事件:

1、出發時刻:從決策點集中選點決策;

2、到達時刻:把第 \(i\) 個點加入所到達站點的決策點集。

把 \(2m\) 個時間按時間排序,就可以用單調佇列維護。

\(p.s.\):由於時間不超過 \(1000\),直接暴力在凸包上選點可過 (考場親測)。

時間複雜度由於排序可以用 \(vector\)、鍊錶等時間是線性的 \(o(m + t)\),其中 \(t\) 為最大時刻。

#include #include #include #include int in() 

templateinline void chk_min(t &_, t __)

templateinline void chk_max(t &_, t __)

const int n = 1e5 + 5;

struct node a[n << 2];

std::vectorq[n], b[2][1001];

int fro[n];

int n, m, a, b, c;

long long f[n << 1];

inline bool chk1(int j, int k, int m)

inline bool chk2(int j, int k, int i)

int main() ;

a[i + m] = (node);

std::swap(a[i].t, a[i + m].x);

b[0][a[i].t].push_back(i), b[1][a[i + m].t].push_back(i + m);

}memset(f, -1, sizeof(f));

for (int tim = 1, i; tim <= 1000; ++tim)

if ((int)q[a[i].x].size() > fro[a[i].x])

}for (unsigned p = 0; p < b[1][tim].size(); ++p)

q[a[i].x].push_back(i);}}

}long long res = -1;

for (int i = 1; i <= m; ++i)

if (a[i + m].x == n && ~f[i])

if (!~res)

res = f[i] + a[i + m].t;

else

chk_min(res, f[i] + a[i + m].t);

printf("%lld\n", res);

return 0;

}

updating……

學習筆記 斜率優化DP

作為數學渣,先複習一下已知兩點 x 1,y 1 x 2,y 2 怎麼求過兩點的一次函式的斜率.待定係數法代入 y kx b 有 x 1k b y 1 x 2k b y 2 兩式相減有 k frac 故事圍繞著 演算法競賽高階指南 的三一道例題展開 任務安排 1 假如我們啟動了乙個任務 l,r 那麼它...

斜率優化dp筆記

瞎扯 演算法真的是無止境,從暴力到dp原本以為很神奇了,沒想到還能優化dp,而且是把o n 2 變成o n 真是無 說。引入 我們來分析這麼乙個問題,給你n個數,要你把他們分成連續的若干塊,使得讓他們的每段和的平方加起來最小.正常我們會想到的就是o n 2 的dp,方程就是 dp i min dp ...

斜率優化DP 學習筆記 更新中

參考資料 1.元旦集訓的課件已經很好了 2.一 對於一類轉移方程 f i max a i 和c i 是開始求解前就知道常數,b j 和d j 知道f j 後就知道有關 可以使用斜率優化 不是這個形式就盡量往這個形式化 決策單調性 對於兩個轉移j和k,設b j 假設j比k優或相等,把式子一化就變成了 ...