多重揹包2
混合揹包
與01揹包不同的是,多重揹包的每乙個物品有s件,而01揹包每個物品有1件。
我們是不是可以進行乙個拆分,把這s件物品拆成01揹包的模型來計算。
我們再看物品的數量,假設最多的100件物品,每個物品可以取100次,我們使用三重迴圈的話,時間複雜度是100 * 100 * 100
,也就是10的6次方
。而c++程式一秒大概可以執行10的7次方 ~ 10的8次方左右
的次數。
也就是說我們簡單使用三重迴圈的暴力方法是可以過的。
看了一眼資料範圍,1000 * 2000 * 2000
,直接暴力三重迴圈肯定超時了。
提示中顯示,可以使用二進位制優化的方法,也就是使用二進位制對揹包進行壓縮。
我們直接把所有物品都變成乙個乙個的肯定不行,我們可以利用二進位制獨特的壓縮方式,可以把多個物品壓縮成乙個物品,這樣物品的數量壓縮的範圍簡化到1000 * log(2000)
,時間複雜度近似於1000 * 11 * 2000
,我們看這是可以在1s 中跑完的,時間複雜度可以通過了。
;//存放壓縮後物品的倉庫
typedef
struct good
good;
intmain()
);s -
= k;
}//不能分解的,單獨構成乙個物品
if(s) goods.
push_back()
;}//安裝01揹包的模板進行遍歷
我們可以看到,在這個題中,乙個物品有三種型別,一種可以使用1次(01揹包),一種可以使用無限次(完全揹包),最後一種可以使用多次(多重揹包)。
而且時間複雜度也是挺高的,1000 * 1000 * 1000
,10的9次方,已經超過了c++1秒的執行次數。
和上面的多重揹包問題相同,我們可以採用壓縮的方式,將多重揹包都利用二級制的思想壓縮為01揹包,然後分情況來解決混合揹包的問題。我們就把題目變成了01揹包和完全揹包的情況。
時間複雜度1000 * 11 * 1000 + 1000 * 1000
,這是完全可以的。
#include
#include
#include
using
namespace std;
const
int n =
10010
;struct good
;vector goods;
int dp[n]
;int
main()
);else);
s -= k;}if
(s) goods.
push_back()
;}}//計算
for(
int i =
0; i < goods.
size()
; i++)if
(goods[i]
.s ==-1
)//01揹包
for(
int j = m; j >= goods[i]
.v; j--
) dp[j]
=max
(dp[j]
, dp[j - goods[i]
.v]+ goods[i]
.w);
else
//多重揹包問題
for(
int j = goods[i]
.v; j <= m; j++
) dp[j]
=max
(dp[j]
, dp[j - goods[i]
.v]+ goods[i]
.w);
cout<
<
return0;
}
0 1 完全揹包 多重揹包問題 混合揹包
0 1揹包問題 dp i j 表示前i件物品,體積容量為j的揹包所能獲得的最大價值 決策是第i個物品選不選 轉移方程 dp i j max dp i 1 j dp i 1 j v i w i n為物品數量,m為揹包體積 for int i 1 i n i for int j 0 j m j if j...
大家都知道的01揹包問題
一維解法 拓展問題 完全揹包 對於每乙個物品,在揹包容量足夠的情況下,我們有兩種狀態,一種是把該物品放在揹包,一種是不把該物品放在揹包。我們建立乙個二維的陣列,dp i j 表示前 i 個物品,在容量為 j 的時候,最大價值。v i 表示物品所佔的體積 w i 表示物品的價值 把該物品放在揹包 dp...
揹包學習 多重揹包揹包
有n種物品和乙個容量為v的揹包。第i種物品最多有n i 件可用,每件費用是c i 價值是w i 求解將哪些物品裝入揹包可使這些物品的費用總和不超過揹包容量,且價值總和最大。狀態轉移方程 f i v max 此時他面臨的不是01揹包的選與不選的問題,而是從n i 裡面選多少個的問題。實現方法 1 轉化...