0 1揹包問題 從暴力到一維vector的優化

2021-10-23 11:45:48 字數 2804 閱讀 5935

0-1揹包問題

分析:同樣,若沒有思路可以考慮暴力迴圈的方法,即先找到多少種情況(2n),再每一種情況是否符合要求並求價值,求取最大值,o((2n)*n)。

若進一步考慮,可定義表示式:f(n,c),意思為將n個物品裝入容量為c的揹包中,能取得的最大值。如下圖所示,採用遞迴的方式可以避免暴力。對於第n個物品,可以有兩種取法,取(1)或不取(0),當取的時候,則最大值為v(n)+f(n-1,c-wn),即將n-1個物品裝入c-wn的容量中,所能得到的最大價值;當不取的時候,則為f(n-1,c),因為沒取n,故容量不變。那麼,若採取遞迴計算的話,實際上每層求max(v(n)+f(n-1,c-wn),f(n-1,c)),並返回給最上層即可。

// 遞迴法解決0-1揹包問題

class solution

};int main()

; vectorvalue = ;

solution s;

cout<

return 0;

}可採用記憶化搜尋對氣優化

#include "pch.h"

#include #include #include using namespace std;

// 遞迴法解決0-1揹包問題

class solution

};int main()

; vectorvalue = ;

// 3、

vector> memo(weight.size(), vector(6, 0));

solution s;

cout<

return 0;

}

進一步,由於該遞迴中存在最優子結構,故可從下到上採用動態規劃的辦法。可參考機器走路問題82。不過本題中二維條件不夠明顯,需進一步分析。首先,題中要求,n個物品最多可裝入容量為c的揹包的最大價值,寫成表示式為f(n,c),那麼這是乙個二維函式,將82中的豎座標當作n,橫座標當作容量c,那麼f(i,ci)代表前i個物品裝入ci揹包中能得到的最大價值。。接下來需要找狀態轉移方程,由於揹包可裝可不裝,那就分情況討論,若i裝,則f(i,ci) = vi+f(i-1,ci-wi):即第i個物品的價值,加上,前i-1個物品裝入ci-wi揹包中的最大價值。若i不裝入,則f(i,ci) = f(i-1,ci):即前i-1個物品裝入ci揹包中的最大價值。故狀態轉移方程為f(i,ci) = max(vi+f(i-1,ci-wi),f(i-1,ci))。

#include "pch.h"

#include #include #include using namespace std;

// 動態規劃解決0-1揹包

int main()

; // 物品重量

vectorvalue = ; // 物品價值

// 當成二維圖形,橫座標為容量,縱座標為物品

int c = 5;

vector> dp(weight.size(), vector(c+1, 0));

// 第一列不用賦初值,因為第一列的容量都為0,故不可能放入物品

// 先將第一行賦初值

for (int i = 0; i <= 5; i++)

for (int i = 1; i < weight.size(); i++) }

cout << dp[weight.size()-1][5];

return 0;

}

動態規劃的優化基本上均是盡可能降低空間複雜度。通常是二維變一維,一維變變數。

1、從上述迴圈中可以看到,每次迴圈只用到了兩行資料,故可用求餘進行處理。

2、再進一步分析,可從右向左進行重新整理,這樣只儲存一行資料就可不斷求得值

// 1、變為兩行陣列

// 動態規劃解決0-1揹包

int main()

; // 物品重量

vectorvalue = ; // 物品價值

// 當成二維圖形,橫座標為容量,縱座標為物品

int c = 5;

// 優化1、

vector> dp(2, vector(c+1, 0));

// 第一列不用賦初值,因為第一列的容量都為0,故不可能放入物品

// 先將第一行賦初值

for (int i = 0; i <= 5; i++)

for (int i = 1; i < weight.size(); i++) }

// 優化3、

cout << dp[(weight.size()-1) % 2][5];

return 0;

}

// 動態規劃解決0-1揹包

int main()

; // 物品重量

vectorvalue = ; // 物品價值

// 當成二維圖形,橫座標為容量,縱座標為物品

int c = 5;

// 優化1、

vectordp(c+1, 0);

for (int i = 0; i <= 5; i++)

for (int i = 1; i < weight.size(); i++) }

// 優化3、

cout << dp[c];

return 0;

}

從01揹包到多重揹包

時隔多年,重拾揹包dp,簡單的看了看01揹包,完全揹包和多重揹包。在航電上隨便看了一題多重揹包竟然wa了一發。仔細的整理了一下,然後發現多重揹包實際上就是01揹包。首先說一下01揹包和多重揹包的區別和相似點 人擁有的購買力是一定的,每個物品的 和價值是固定的,這是簡單揹包問題的共性暫且不說。最重要的...

暴力法求解01揹包問題

這段 只是使用暴力法解決了01揹包問題,但是沒有經過優化,效率不高。使用暴力法的原因只是因為作業需求,請勿評價。主要的難點在於使用c語言列出乙個陣列的所有子集。使用了遞迴的方法,將每次的計算都歸併為二個元素,這樣就能夠簡化問題。main.c backpack created by shadowdai...

揹包問題(一) 0 1揹包問題

揹包問題有多種,比如 問題1 物品受限揹包,第i種物品最多取ni個 問題2 0 1揹包,本文即將介紹,xi 0或者1,i 1 2 3.n 問題3 多揹包問題,m個揹包,揹包j裝入最大重量bj,j 1 2 3.m,在滿足所有揹包重量約束 條件下使得裝入物品價值最大 問題4 二維揹包,每件物品有wi和體...