0 1揹包問題

2021-07-15 18:51:11 字數 2116 閱讀 7175

揹包問題,常見的有三種型別:基本的0-1揹包、完全揹包和多重揹包、二維揹包 

首先是基本的0-1揹包問題。因為這裡的物品一般指花瓶、玉器什麼的,要麼拿、要麼不拿,只有0和1兩種狀態,所以也叫0-1揹包。0-1揹包雖然簡單,卻很重要,是「萬法之源」,是其他幾類問題的基礎。 

初學者有時會認為,0-1揹包可以這樣求解:計算每個物品的vi/wi,然後依據vi/wi的值,對所有的物品從大到小進行排序。其實這種貪心方法是錯誤的。如下表,有三件物品,揹包的最大負重量是50,求可以取得的最大價值。 

其實,0-1揹包是dp的乙個經典例項,可以用動態規劃求解。

dp求解過程可以這樣理解:對於前i件物品,揹包剩餘容量為j時,所取得的最大價值(此時稱為狀態3)只依賴於兩個狀態。

狀態1:前i-1件物品,揹包剩餘容量為j。在該狀態下,只要不選第i個物品,就可以轉換到狀態3。

狀態2:前i-1件物品,揹包剩餘容量為j-w[i]。在該狀態下,選第i個物品,也可以轉換到狀態3。

因為,這裡要求最大價值,所以只要從狀態1和狀態2中選擇最大價值較大的乙個即可。 

狀態轉換方程:

dp( i,j ) = max( dp( i-1, j ), dp( i-1, j-w[i] ) + v[i] )

dp( i,j )表示前i件物品,揹包剩餘容量為j時,所取得的最大價值。 

還是結合上面的例子來說明吧。有三件物品,揹包的最大負重量是50,求可以取得的最大價值。下圖表示了dp自上而下的求解過程。

程式設計實現:

一般來說,有了狀態方程,直接程式設計實現就game over。dp( i,j ),用乙個二維陣列來實現,然後用乙個兩層迴圈就可以了。不過,有時選擇的物品很多,揹包的容量很大,這時要用二維陣列往往是不現實的。這裡有乙個方法,可以進行空間壓縮,然後使用一維陣列實現。

還是結合上面的例子,有三件物品,揹包的最大負重量是5,求可以取得的最大價值。為了方面說明,物品weight依次為:1,2,3。二維陣列下的求解順序,物品數1--->n, 揹包容量1--->w。如圖,要使用一維陣列,揹包容量要採用倒序,即w--->1, 只有這樣對於方程dp( j ) = max( dp( j ), dp (j-w[i] ) + v[i] ),才能達到等式左邊才表示i,而等式右邊表示i-1的效果。poj對於題目:3624。下面附**。

完全揹包和多重揹包。有了基本的0-1揹包基礎,下面的東西也就好理解了。 完全揹包,指每個物品有無限多個。 多重揹包,指每個物品的數量是有限的。當然,這時的問題不再是拿與不拿,而是拿多少的問題,當然不能超過揹包容量。 

根據上述分析的最優解的結構遞迴地定義問題最優解。設c[i,w]表示揹包容量為w時,i個物品導致的最優解的總價值,得到下式。顯然要求c[n,w]。

編碼實現:

如果直接編碼,用三層迴圈,往往會超時。這樣有一種很有效的壓縮方式:二進位制壓縮。把原來的物品按照2的n次方進行重新組合。用1、2、4、8…進行組合,可以組合出任意的數字。poj題目:1276

#include using namespace std;

/***

c[i][w]表示揹包容量為w時,i個物品導致的最優解的總價值,大小為(n+1)*(w+1)

v[i]表示第i個物品的價值,大小為n

w[i]表示第i個物品的重量,大小為n

***/

void dp(int n, int w, int c[18], int *v, int *wei)

else

else

c[i][w] = temp;

}} }

}void findpath(int c[18], int *x, int *wei, int n, int w)

else

}if (c[1][w] == 0)

x[0] = 0;

else

x[0] = 1;

}int main()

; int v = ;

int c[6][18] = ;

dp(n, w, c, v, w);

cout<

揹包問題 01揹包問題

n個物品,總體積是v,每個物品的體積的vi,每個物品的最大價值是wi,在不超過v的體積下求最大價值 eg揹包容積為 5 物品數量為 4 物品的體積分別為 物品的價值分別為 思路定義乙個二位陣列int f new int n 1 v 1 f i j 就表示在1 i個物品中選取體積小於v的情況的最大價值...

揹包問題 01揹包

有n件物品和乙個容量為v的揹包。第i件物品的重量是c i 價值是w i 求解將哪些物品裝入揹包可使價值總和最大。01揹包中的 01 就是一種物品只有1件,你可以選擇放進去揹包即1,也可以選擇不放入揹包中即0。include include using namespace std const int ...

揹包問題(01揹包)

1085 揹包問題 在n件物品取出若干件放在容量為w的揹包裡,每件物品的體積為w1,w2 wn wi為整數 與之相對應的價值為p1,p2 pn pi為整數 求揹包能夠容納的最大價值。input 第1行,2個整數,n和w中間用空格隔開。n為物品的數量,w為揹包的容量。1 n 100,1 w 10000...