目錄怎麼dp
遞迴、有記憶的遞迴(自上而下記憶法)、自下而上填表法的區別
揹包類問題的求解誤區
在學動態規劃思想之前求解裝包類問題時,很容易想到根據價效比排序優先裝高價效比物品的貪心演算法,這就有點像線性規劃,連續型變數我們可以通過求導來計算,但涉及到整型就會很頭疼了:
想要舉反例很簡單,比如只有兩個物品:物品a:價值5,體積5,物品b:價值8:體積7,揹包容量為10,物品b的價效比顯然要比物品a高,那麼用貪心演算法必然會選擇放入乙個物品b,此時,剩餘的空間已無法裝下a或者b,所以得到的最**值為8,而實際上,選擇放入兩個物品a即可得到更高的價值10。所以這裡貪心演算法並不適用。再比如零錢兌換問題也會陷入這樣的誤區。完全揹包問題。
哪些問題適用dp
動態規劃理論部分
1.1. 最優化原理
全域性最優策略的子策略也必須是子問題的最優解。
1.2. 無後效性
當下決策不看過去(過去對當下的選擇沒有影響),馬爾科夫決策。
兩個反例參考01揹包問題
相關問題整理
首先是最優解問題,最優解問題通常都可以先考慮下是否可以用dp來求解(找子問題,要滿足最優化原理和無後效性的特點),通常會用min、max來在子問題解的基礎上進行選擇。
比較典型的就是揹包問題(各種求和/填充問題)、子串行問題,通常都會有分階段選擇決策的步驟。
像目標和問題雖然不是最優化問題,但也是個揹包問題,可以用dp來求解,它其實不是決策,而是在用dp儲存方法數並傳遞,所以用的不是max/min,而是加法。
dp的關鍵在於找到當前問題與子問題的遞推關係式,並且要正確地設定邊界值。
使用遞推關係式,假設子問題已經求出最優解,當前問題的決策只需在子問題最優解的基礎上選取當下的動作,然後考慮怎麼將當下動作和子問題的最優解相結合(即,dp用來存什麼以及怎麼算)。
通過以下幾個問題練習一下問題分解以及遞推關係式(可以在leetcode中搜尋題目):
以上幾類算是比較經典的簡單dp問題,初次見到時建議自己手動算,在計算的過程中發現重疊的子問題,然後找出遞推公式,熟悉了後記住這幾類問題的子問題切入點,面試經常會問到。像揹包、投資、路徑選擇問題,子問題還是比較顯而易見的,但最長子序列和連續子串行(字串)問題,就要記住子問題怎麼切入:
//揹包問題的求解
public int binpack(int w, int v, int capacity, int n_items)
// |
// v
// for (int k = 0; k*w[i] <= j && k <= n[i]; k++)
// 0-1揹包問題的options[i]就是0/1(也是特殊的完全揹包/多重揹包問題),完全揹包問題的options[i]就是滿足k*w[i]<=j的k,多重揹包問題的options[i]就是滿足k<=n[i]&&k*w[i]<=j的k。
if (w[i] < j) else
} }
}//也有一維的揹包dp,但個人認為二維的更好理解(也可能是我刷題太少了),在遇到新問題時,這種多一維的更容易想到。
參考01揹包問題可以更清楚地區別回溯法、遞迴、動態規劃之間的區別與聯絡。
不管是遞迴還是動態規劃(這裡說自上而下記憶法,也就是有記憶的遞迴),都需要找出問題與子問題之間的遞推關係式,至於需不需要儲存記憶,就看子問題有沒有重疊部分了(比如斐波那契數列),儲存記憶可以避免重複求解,這就是遞迴不同於動態規劃的地方。
而回溯、dfs是遍歷解空間的思想,即使有剪枝,其遍歷空間還是比dp要大很多,因為dp使用最優解遍歷時避免了對差解的遍歷。
以0-1揹包問題為例,遞迴的時間複雜度為capacity * n_items * 2;而dfs的時間複雜度為2^n_items。
動態規劃整理(二)
題目描述 給定乙個只包含正整數的非空陣列。是否可以將這個陣列分割成兩個子集,使得兩個子集的元素和相等。注意 每個陣列中的元素不會超過 100 陣列的大小不會超過 200 分析 自頂向下分析 我們先得到一半的值是多少 在進行填充 與01 揹包不同的是 不受權重影響,但卻必須得填滿揹包 從 n個數字裡取...
動態規劃經典題目整理
複雜度 o n w o nw o nw n nn為物品種類,w ww是揹包的重量 目的 使得揹包中的物品價值最大化 單副本揹包問題 每種物品只有一件 k w j ma xk w,j max k w,j max k w j k w,j k w,j 代表揹包重量為w ww,有j jj件物品時候的最大價值...
動態規劃習題整理(1)
狀態表示 f i 表示以第 i 個元素結尾的所有連續子陣列的最大值。狀態轉移 f i max f i 1 0 nums i f i 可劃分為兩部分,以第 i 1個元素結尾的所有連續子陣列加上第i個元素,或者只選用第 i 個元素。答案為所有f i 中的最大值。優化 由於f i 在計算時只會用到f i ...