0 1揹包問題的個人理解

2021-09-17 20:10:04 字數 1325 閱讀 9746

問題:

給乙個能承重v的揹包,和n件不同物品(每個物品只有一件),我們用重量和價值的二元組來表示乙個物品,第i件物品表示為(vi,wi),問:在揹包不超重的情況下,得到物品的最大價值是多少?

最近做了不少題,不像以前那樣水部落格了2333,總結一下,運用動態規劃解決此類問題,首先確定遞推狀態 f ( i , j ) = k;其中 k 表示為 i 件物品,剩餘承重為 j 的情況下能裝的最大價值,則影響 k 值的有兩個因變數分別為 i, j ;所以我們建立二維陣列 a[ i ][ j ]來表示在 i 件物品剩餘承重為 j 時揹包能裝的最大價值。

在確定了狀態以後我們開始確定狀態轉移方程:很顯然向背包內放物品 i 時會有兩種可能的情況,第一種為超重,既物品重量  vi > 當前揹包剩餘重量 j  ,揹包無法放入物品,此時揹包價值與 i - 1 一致,不發生變化,另一種為 vi <= j,在此狀態下我們可以選擇在 i - 1的基礎上放入當前物品或者不放入當前物品,有很多情況下我們放入物品 i 並不能求出最大價值,此時需要對放或者不放兩種情況的揹包價值進行比較,取價值高的一者,既 max( a[ i - 1 ][ j ] , a[ i - 1 ][ j - vi] + wi ) ;當選擇放入物品時需對剩餘承重和當前揹包的價值進行更新。

**:#include#includeusing namespace std;

int main()

memset(a,0,sizeof(a));

for(int i = 1; i <= n; i++)else}}

cout《在此基礎上我們可以進行一下優化,減少空間的開銷,二維陣列的開銷是巨大的,我們可以採用滾動陣列的方式對 a 陣列進行處理

#include#includeusing namespace std;

int main()

memset(a,0,sizeof(a));

for(int i = 1; i <= n; i++)else}}

cout《繼續對其進行優化,我們能發現 a[ i ][ j ]的值是由 a[ i-1 ][ j ] 或  a[ i-1 ][ j - vi ] + wi 決定的,而 i - 1實際上是上一次迴圈算出的數值,我們可以將a壓縮為一維陣列 a[ j ] (j代表剩餘承重量),由於第 i 個物品需要用到第 i - 1個物品時的狀態值,迴圈應從後向前推進,避免之前的值在未被利用前就被改變(既當進入一層迴圈時由末尾最後一位開始,前面的都是上乙個 i 迴圈產生的值)

#include#includeusing namespace std;

int main()

memset(a,0,sizeof(a));

for(int i = 1; i <= n; i++)}}

cout《可達到線性時間。

01揹包問題的理解

01揹包是 n個物品重量和價值分別為w i v i 揹包可以容納的重量為weight,怎麼裝下最大價值的物品?狀態轉移方程是 value i,w max value i 1,w w i v i value i 1,w 要求w的解,那麼先求w w i 的解,w w i 的值只有在知道了i是多少時才知道...

揹包01問題初理解

揹包問題 knapsack problem 是一種組合優化的np完全問題。問題可以描述為 給定一組物品,每種物品都有自己的重量和 在限定的總重量內,我們如何選擇,才能使得物品的總 最高。問題的名稱 於如何選擇最合適的物品放置於給定揹包中。具體理解可以直接通過下面的例子來理解揹包問題 揹包問題的乙個例...

01揹包問題深度理解

有n件物品和乙個容量為v的揹包,求可以得到的最大價值。其中重量是w i 價值是v i 例 4 5 1 22 3 3 42 2 01揹包問題的常用的f v max f v f v w i v i 的解法是由樹遞迴得來的,這裡從頭推演一遍。我們可以這樣理解,從第乙個物品開始,每個物品都有兩種情況 選或不...