動態規劃如何輸出路徑?

Tech In Pieces發表於2020-12-19

動態規劃的大部分題目 都是不需要輸出具體的路徑的,但是萬一要輸出路徑呢?
下面來看一下動態規劃如何輸出路徑,以揹包問題為例:

一般而言,揹包問題是要求一個最優值,
如果要求輸出這個最優值的方案(路徑),可以參照一般動態規劃問題輸出方案的方法:記錄下每個狀態的最優值是由狀態轉移方程的哪一項推出來的,換句話說,記錄下它是由哪一個策略推出來的。便可根據這條策略找到上一個狀態,從上一個狀態接著向前推即可。
這也就意味著 我們必須要維護一個狀態陣列 這個陣列和DP陣列一樣,每個元素必須記錄著這個狀態是由哪個元素轉移過來的。也就是說 我們要知道我們選擇當前的座標 是由哪個座標跳過來的。所以我們在每個點就存上一個點的座標。
或者我們選擇哪個就把哪個座標點標記為1 如果我們並不決定要走那個點 就把其重新覆蓋為0.
輸出字典序最小的最優方案:這樣的話 跟我們選擇的順序有關係 --感覺這就完全改變了這個問題。解決方案並沒有看懂
求次優解/第K優解: 我們的思路還是動態規劃 狀態轉移方程也沒有變化。唯一有變化是 針對每個點 我們不是隻存一個當前最優值 而是存所有的可能的值(其實也不是所有可能的值 而是最大或者最小的k個值(至於為什麼這樣 見附錄的解釋)),將之放進PQ裡面,每次要每個狀態都試一遍。最後在陣列的最後 輸出PQ種poll出來的第K個元素即可。

附錄:
為什麼我們合併兩個序列a b
假設第一個序列長為m 第二個為n
我們只需要取第一個序列前k個和第二個序列的前k個
合併得到的長度為2k的序列 這個序列一定包含a+b的前k個最大的元素。
為什麼呢?

假設
a = [a1 a2 a3 a4 a5] 從大到小
b = [b1 b2 b3 b4 b5] 從大到小
k=3
我們取a的前三個和b的前3個 這六個元素一面一定包含 [a1 a2 a3 a4 a5 b1 b2 b3 b4 b5] (亂序)的前k大的元素。
證明:
[b1 + a1, b1 + a2, b1 + a3]就已經比[b1 + a4]大了 所以已經存在k個比b1+a4大的了 所以這個組合肯定沒有機會進入前K大。所以每個取前k個就足夠了。

refer:
dd大牛的揹包九講-揹包問題彙總

相關文章