揹包問題(knapsack problem)是一種組合優化的np完全問題。問題可以描述為:給定一組物品,每種物品都有自己的重量和**,在限定的總重量內,我們如何選擇,才能使得物品的總**最高。問題的名稱**於如何選擇最合適的物品放置於給定揹包中。相似問題經常出現在商業、組合數學,計算複雜性理論、密碼學和應用數學等領域中。也可以將揹包問題描述為決定性問題,即在總重量不超過w的前提下,總價值是否能達到v?它是在2023年由merkle和hellman提出的。問題描述:
有n個重量和價值分別為wi,vi的物品,從這些物品中挑選出總重不超過m的若干物品,使挑選出的物品價值最高。
思路:如果使用暴力列舉的思想,01揹包問題的時間複雜度是非常高的,並不適合在演算法競賽中使用。
而貪心的思想也並不適用,舉個例子,對於資料
n = 3, m = 4w =
v =
如果優先選擇價效比(即價值 / 重量)最高的物品,那麼揹包在裝入1號物品後便無法再裝入剩餘物品,此時揹包總價值為5,然而實際上的最優方案是選擇2,3號物品,總價值為6。
對於01揹包問題,通常採用動態規劃的方案。
1for (int i = 1; i <= n;i++)
2for (int j = 0; j <= m;j++)
3
定義陣列 f(i,j) 表示對於前 i 個物品,揹包容量為 j 時可以得到的最大容量
狀態轉移方程為
f[i][j] = max(f[i - 1][j], f[i - 1][j - w[i]] + v[i]);
簡單的解釋就是,對於第 i 件物品,如果拿上它後背包的大小比不拿上它要大,就拿上它
以上寫法的空間複雜度還可以進行優化
for (int i = 1; i <= n; i++)
只需要一維陣列,j 從後往前遍歷,j 右側相當於前一種寫法中的 f(i, j) 左側相當於 f(i - 1, j) 只需要一維陣列便可以儲存最終結果,實現了對空間複雜度的優化。
問題描述:
有n種重量和價值分別為wi,vi的物品,從這些物品中挑選出總重不超過m的若干物品,每種物品的數量不限,使挑選出的物品價值最高。
思路:完全揹包可以看作01揹包的乙個變種,區別在於01揹包每種物品只有乙個,而完全揹包問題中每種物品有無限個
所以只需要稍微修改01揹包的程式
for (int i = 1; i <= n; i++)
對於第 i 種物品,只要揹包仍有足夠空間,就可以盡可能的嘗試往裡放,因此 j 的迴圈可以從 w[i] 一直到 最大空間 m 為止。
問題描述:
有n種重量和價值分別為wi,vi的物品,每種物品的數量為ki ,從這些物品中挑選出總重不超過m的若干物品,使挑選出的物品價值最高。
思路:對於多重揹包問題,如果把每種物品看作 k 個不同的物品,那麼這個問題就可以轉化為普通的01揹包問題。但是這樣做並不是最優的做法
常用的劃分方式,可以將每種物品劃分為數種物品,其中每種物品的重量和價值等於 2^0, 2^1, 2^2……2^(n-1) , k - 2^(n-1 )倍的 w 和 v 。這樣的劃分方式可以使得劃分後物品的總價值和總重量不變,同時也可以通過組合的方式實現1——k任意一種數量的選擇。
1int cnt = 0;2
3for (int i = 0; i < m; i++)
415 c[++cnt] = a *s;
16 w[cnt] = b *s;
17 }
實現劃分之後,可將問題作為普通的揹包問題求解。
動態規劃初步(一)01揹包問題
首先,我們設想乙個場景 當你準備外出的時候,你有乙個容量有限的揹包,還有若干個想要帶走的物品,每個物品都有它的體積和在你心中的價值。但是呢,因為揹包容量有限,你只能選擇部分帶走。這時,我們就得到了乙個問題,如何才能夠使得揹包裝的價值總量最大呢?現假設,揹包的容量是t,共有n個物品,第i個物品的體積為...
揹包問題 01揹包問題
n個物品,總體積是v,每個物品的體積的vi,每個物品的最大價值是wi,在不超過v的體積下求最大價值 eg揹包容積為 5 物品數量為 4 物品的體積分別為 物品的價值分別為 思路定義乙個二位陣列int f new int n 1 v 1 f i j 就表示在1 i個物品中選取體積小於v的情況的最大價值...
01揹包問題 完全揹包問題 多重揹包問題
0 1 揹包問題 給定 n 種物品和乙個容量為 c 的揹包,物品 i 的重量是 wi,其價值為 vi 問 應該如何選擇裝入揹包的物品,使得裝入揹包中的物品的總價值最大?分析一波,面對每個物品,我們只有選擇拿取或者不拿兩種選擇,不能選擇裝入某物品的一部分,也不能裝入同一物品多次。解決辦法 宣告乙個 大...