DP 的本質
一般 DP 的本質
- 狀態:點。(帶了值)
- 轉移:邊。
- DP:在 DAG 上推。(得到 / 更新 點的值)
特殊(類似 DP)
圖不是 DAG。有兩種思路:
- 解方程
- 簡單的:直接解(比如只有一個環)。
- 複雜的:高斯消元。
- 高斯消元。
- 高斯-約旦消元。
- 圖論
- 類似最短路:
- Dijkstra 演算法 / 類似 Dijkstra 的演算法。
- SPFA 演算法 / 類似 SPFA 的演算法。
- 其他的我可能還不知道。
- 類似最短路:
DP 的要素
(我目前想起來的。)
- 狀態。無後效性,設計方式:把之後要用的全部塞進狀態裡。
- 轉移方程。就近轉移,不重不漏。最值(min、max)、其他運算。
- 初值。按定義 / 為了轉移後得到的狀態的值正確。[也許要為了之後正確用奇怪的定義。](?)(好像是 重返現世 那題)。[注意特殊情況。](之前寫的,現在不知道例子是什麼)
- 最終答案。可能是一個狀態,可能是多個狀態運算起來。
可能一般按 狀態 -> 轉移方程 -> 初值、最終答案 的順序思考。
DP 的轉移方式
之前聽說叫“填表法”和“刷表法”。
推到其他狀態
在當前狀態上做改動。個人認為更符合正向思維。
似乎轉移對應關係複雜的時候用這種方式比較清晰方便。
從其他狀態轉移來
找之前的狀態。個人認為更符合逆向思維。
似乎更常用。
似乎在決策方面最佳化 DP 的時候常用。比如 單調棧、單調佇列、斜率、決策單調性、線段樹之類的 DS 大力找決策點 最佳化 DP。
DP 的轉移順序
按拓撲序
(我知識水平非常有限,不太瞭解拓撲序,這裡說拓撲序可能不止一種是不嚴謹的或錯誤的,但是就是這個意思 qwq。)
一般的轉移順序。本質上是按照 DAG 的拓撲序。
注意拓撲序可能不止一種,有時換一種順序可能可以最佳化 DP,換順序如:二維狀態的 DP,先列舉哪一維後列舉哪一維可能可以顛倒。(如:把序列分割成給定個數個區間的題。)
記憶化搜尋
避免了轉移順序的問題。
注意初始化 \(vis\) 陣列(或者直接把 \(f\) 初始化成 \(-1\) 之類的)。
時間複雜度[一般要](?)結合狀態數來分析,但不一定等於狀態數,可能還要算上轉移和其他的代價。(如二維區間 DP。)
典型例子是數位 DP、二維區間 DP。