從01揹包到多重揹包

2021-08-14 21:08:09 字數 980 閱讀 2613

時隔多年,重拾揹包dp,簡單的看了看01揹包,完全揹包和多重揹包。在航電上隨便看了一題多重揹包竟然wa了一發。

仔細的整理了一下,然後發現多重揹包實際上就是01揹包。

首先說一下01揹包和多重揹包的區別和相似點:

人擁有的購買力是一定的,每個物品的**和價值是固定的,這是簡單揹包問題的共性暫且不說。最重要的一點是,01揹包問題和多重揹包問題的物品的數量都是有限的(01揹包每件物品只有乙個,而多重揹包的物品數量為有限個);而這種特性決定了多重揹包本質上就是01揹包,如若將多重揹包中的每乙個物品當成不同的物品(即使他們的**和價值是相同的),那麼這樣的每一件物品仍然可以看作每一件物品只有乙個,有取和不取兩個選擇。就是乙個裸的01揹包題目了。當問到最優情況下,每種物品分別取多少的時候也是可以很簡單在此基礎上做到的。

因此,多重揹包的種類×數量二維就可以當作01揹包的物品種類這一維,當我們dp的時候,01揹包如果使用降低空間複雜度的做法,也就是將dp[w]簡化為dp[w]時,因為此時的dp[w](dp[w])需要由dp[w-w]推算得到。從前推dp[w]會導致dp[w-w]的值由dp[w-w]覆蓋,從而得到錯誤的結果。由於多重揹包和01揹包的本質相同,所以多重揹包的dp[w]也須從後往前推得。

明白了這一點,三種簡單揹包:01揹包,完全揹包和多重揹包的dp遞推方法就顯而易見了。

值得說的是,通過這種拆分的思想,可以減少一部分時間複雜度的。

不過在拆的時候不能將cn拆成1+1+1+1+1+1.....+1的形式。這麼做會超時。應該將cn拆成 cn=1+2+4+8+...+(cn-sum)。  這裡sum表示前面的數字之和,例如 按照規律加到第m個數,發現已經大於cn,那麼sum就表示從 1+2+4+8+.....+ 2^(m-2)。  

我們可以檢驗,在[1,cn]中任意的數 我們都可以在這個序列中找到若干數相加得到。

拆分結束後我們就可以按照01揹包求解。 dp[j]=max(dp[j],dp[j-cos[i]]+val[i]) 。

時間複雜度為 o(w*sigma(logci)) 

揹包 01揹包,完全揹包,多重揹包

哈哈 01揹包 f i v max 完全揹包 f i v max 多重揹包 f i v max include include include include include define maxn 1000 using namespace std int n,cap int w maxn 重量 花...

01揹包 完全揹包 多重揹包

01揹包 zeroonepack 有n件物品和乙個容量為v的揹包,每種物品均只有一件。第i件物品的費用是c i 價值是w i 求解將哪些物品裝入揹包可使價值總和最大。include include includeusing namespace std const int n 1000 10 int ...

01揹包 完全揹包 多重揹包

01揹包 zeroonepack 有n件物品和乙個容量為v的揹包。每種物品均只有一件 第i件物品的費用是c i 價值是w i 求解將哪些物品裝入揹包可使價值總和最大。完全揹包 completepack 有n種物品和乙個容量為v的揹包,每種物品都有無限件可用。第i種物品的費用是c i 價值是w i 求...