揹包九講(4)
阿新 • • 發佈:2022-04-19
揹包九講(4)
多重揹包問題 II
有 N 種物品和一個容量是 V 的揹包。
第 ii 種物品最多有 si 件,每件體積是 vi,價值是 wi。
求解將哪些物品裝入揹包,可使物品體積總和不超過揹包容量,且價值總和最大。
輸出最大價值。
輸入格式
第一行兩個整數,N,V,用空格隔開,分別表示物品種數和揹包容積。
接下來有 N 行,每行三個整數 vi,wi,si,用空格隔開,分別表示第 ii 種物品的體積、價值和數量。
輸出格式
輸出一個整數,表示最大價值。
資料範圍
0<N≤1000
0<V≤2000
0<vi,wi,si≤2000
提示:
本題考查多重揹包的二進位制優化方法。
輸入樣例
4 5 1 2 3 2 4 1 3 4 3 4 5 2
輸出樣例:
10
思路:
本題物品數量和體積都過大,因此要去優化,一般可以考慮將每個物品拆分開來,這樣就是單純的01揹包問題,但是全拆分為1份複雜度過大,因此使用二進位制來優化,所謂二進位制優化就是每次拆除2的倍數,先拆1再拆2,4...當無法拆時,停止即可,這樣需要logS,時間複雜度不會過大,可以接受
#include<iostream> #include<vector> #include<algorithm> using namespace std; const int N = 2020; int f[N]; struct good{ int v; int w; }; int main(){ int n,m; cin>>n>>m; vector<good>goods; //將每種物品拆分(利用2進位制拆分) for(int i=0;i<n;i++){ int v,w,s; cin>>v>>w>>s; for(int k=1;k<=s;k*=2){ s-=k; goods.push_back({v*k,w*k}); } //拆完 有剩餘 放入 if(s>0) goods.push_back({v*s,w*s}); } //拆分完後 就優化成了01揹包問題 使用01揹包模板即可 //列舉每個物品 for(auto good:goods){ //體積從大到小 for(int j=m;j>=good.v;j--){ f[j]=max(f[j],f[j-good.v]+good.w); } } cout<<f[m]; }