【动态规划】01背包问题
01背包問題
問題描述
給定 N 種物品和一個最大載重量為 C 的背包,物品 i 的重量是 wi,其價值為 vi 。 問:應該如何選擇裝入背包的物品,使得裝入背包中的物品的總價值最大?問題分析
對于每個物品,只能選擇裝或者不裝,不能選擇只裝物體的一部分,因此不能使用單位重量的價值進行排序的方法(貪心)來解決,需要用到動態規劃來解決。
動態規劃的三個核心
對于該問題而言,由于第i+1件物品只有兩種選擇(選與不選),因此前i+1件產品的最優解就是前,子結構就是前i件物品裝在承重為j的容器中,可以用result[i][j]來表示。
邊界就是在只裝第一件物品時的情況。
通過上面的對子結構的分析,可以得到狀態轉移方程:
1. j < w[i]時,即剩余載重量不足以裝下當前物品,應有最優解即是前i-1件時的解,result[i][j] = result[i-1][j]
2. j >= w[i]時,即還可以裝下當前物品,因此解應為 裝與不裝 當前物品兩種情況中的最大解。如果不裝,即result[i-1][j];如果裝,,即result[i-1][j-w[i]] + v[i]。因此取最大值結果為result[i][j] = max( result[i-1][j], result[i-1][j-w[i]] + v[i] )。
代碼
1.二維數組
int getLargestValue_1( vector<int> & v, vector<int> & w, int c ) {vector< vector<int> > res( N+1, vector<int>( c+1, 0 ) );/* 該處初始化邊界可以省略由于開始的一列為0,不影響結果 *//*for( int i = 1; i <= c; i++ ) {if( i < w[i] ) {res[1][i] = 0;} else {res[1][i] = v[1];}}*/for( int i = 1; i <= N; i++ ) { //遍歷所有物品for( int j = 1; j <= c; j++ ) { //遍歷容器容量if( j < w[i] ) { //放不下res[i][j] = res[i-1][j];} else { //放的下res[i][j] = max( res[i-1][j], res[i-1][j-w[i]] + v[i] );}}/* 輸出遍歷每件物品的結果 *//* for( int j = 1; j <= c; j++ ) {cout << res[i][j] << ' ';}cout << endl; */}return res[N][c]; }2.兩個一維數組
由于每次遍歷之用到了當前行與上一行,因此可優化空間到兩個一維數組。
int getLargestValue_2( vector<int> & v, vector<int> & w, int c ) {vector<int> preResult( c+1, 0 ); //存儲上次得到的結果,對應上一行vector<int> result( c+1, 0 ); //存儲當前行結果for( int i = 1; i <= N; i++ ) {for( int j = 1; j <= c; j++ ) {if( j < w[i] ) {result[j] = preResult[j];} else {result[j] = max( preResult[j], preResult[j-w[i]] + v[i] );}}for( int j = 1; j <= c; j++ ) {cout << preResult[j] << ' ';}cout << endl;preResult = result;}return result[c]; }3. 一維數組
我們還可以發現每次使用的都是上一行當前列元素上面與左面的元素(preResult[j], preResult[j-w[i]] ),因此我們可以將每行的遍歷順序改變,即從右向左計算,即可將每次的計算結果直接覆蓋到當前位置。
int getLargestValue_3( vector<int> & v, vector<int> & w, int c ) {vector<int> result( c+1, 0 );for( int i = 1; i <= N; i++ ) {for( int j = c; j > 0; j-- ) { //從右向左計算if( j >= w[i] ) {result[j] = max( result[j], result[j-w[i]] + v[i] );}}}return result[c]; }可以使用以下代碼測試:
int main() {vector<int> v{0, 8, 10, 6, 3, 7, 2}; //價值vector<int> w{0, 4, 6, 2, 2, 5, 1}; //重量int c = 12; //最大承載重量cout << getLargestValue_3( v, w, c ) << endl;return 0; }最終答案為24。
總結
以上是生活随笔為你收集整理的【动态规划】01背包问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 原发性不孕症治疗
- 下一篇: 【计算机网络】网络基础