c 多重揹包狀態轉移方程 01揹包問題

2021-10-11 09:00:40 字數 1410 閱讀 9654

最近在刷coursera的演算法課程式設計作業,發現兩年不碰coding實在是忘得差不多了。做到dp題不得不翻翻書了,發現原來動態規劃的基礎就沒怎麼打好,打算寫一些dp的題解。本文主要介紹簡單的動態規劃問題,用於筆者自己整理思路。

從01揹包開始:

用一定的總重量,裝最貴的物品。因為每個物品只有裝與不裝兩種策略,故稱0/1揹包。上題中,單個物品的質量和價值相等(因為是金條,很合理)。

考慮乙個樸素的深搜演算法,複雜度是o(

void
窮舉每個物品放與不放的情況,用當前重量剪枝,最後會形成一棵二叉樹。非常地樸素,當然也非常地慢。

反過來考慮的話,用遞推,對最後乙個物品拿不拿進行分類。可以得到以下的遞推式:

這方便我們寫出乙個遞迴演算法:

int
這個演算法是逆推的,和dfs一樣也是指數複雜度。

由這個遞推方程,或者現在應該叫狀態轉移方程了,不難看出,「考慮第i個元素和餘下wei重量時」的最優解只需知道「考慮第i-1個元素和餘下wei重量時」和「考慮第i-1個元素和餘下wei-w[i]重量時」的最優解。從動態規劃的原理上來講,這滿足最優化原理(最優子結構)和無後效性。從演算法實現的角度,它給了我們乙個遍歷陣列的順序。

先開乙個二維陣列dp[i][wei],那麼根據狀態轉移方程,任何乙個位置的值都可以由它上方和左上方位置的值確定,並且這個過程是遞迴的。

那麼我們自然確定,以先從左往右,再從上往下的順序遍歷陣列。

再預處理一下邊界條件

就可以愉快地dp啦

for
什麼?兩層迴圈?這也太好寫了吧。比前面搜尋,遞迴不知道高到**去了。最重要的是只要

但是呢,聰明的小夥伴已經發現啦,本題呼叫了乙個二維陣列,用了

總結,動態規劃演算法本質在於尋找合法的狀態轉移方程,這一步往往是困難的。帶什麼引數dp?如何構造良好的遍歷順序?從個人經驗來看,從深搜或者遞迴向動態規劃優化可能是一種比較自然的方法。

01揹包的狀態轉移方程

這類問題算是再普通不過了,但是,我忘了。特別是狀態轉移方程,記不清怎麼推導的了,於是在這裡做一下回顧吧 設物品個數為n,每件物品的重量為w i 價值為v i 揹包承重w,我們用乙個二維陣列來表示最大收益,於是得到了方程 if w i 揹包承重j,無法入包 f i j f i 1 j else f i...

揹包 01揹包,完全揹包,多重揹包

哈哈 01揹包 f i v max 完全揹包 f i v max 多重揹包 f i v max include include include include include define maxn 1000 using namespace std int n,cap int w maxn 重量 花...

01揹包 完全揹包 多重揹包

01揹包 zeroonepack 有n件物品和乙個容量為v的揹包,每種物品均只有一件。第i件物品的費用是c i 價值是w i 求解將哪些物品裝入揹包可使價值總和最大。include include includeusing namespace std const int n 1000 10 int ...