有 n 種物品和乙個容量是 v 的揹包。
第 i 種物品最多有 si 件,每件體積是 vi,價值是 wi。
求解將哪些物品裝入揹包,可使物品體積總和不超過揹包容量,且價值總和最大。
輸出最大價值。
輸入格式
第一行兩個整數,n,v,用空格隔開,分別表示物品種數和揹包容積。
接下來有 n 行,每行三個整數 vi,wi,si,用空格隔開,分別表示第 i 種物品的體積、價值和數量。
輸出格式
輸出乙個整數,表示最大價值。
資料範圍
本題考查多重揹包的二進位制優化方法。
輸入樣例
4 5
1 2 3
2 4 1
3 4 3
4 5 2
輸出樣例:10
方法一:
與上一題的多重揹包問題題幹相同,資料增加了乙個數量級,說明要進行優化,否則會tle。這裡的做法是轉化成01揹包問題
對於同一類物品,只要能列舉出其[0, si]中的所有情況就可以了。假如轉化為樸素01揹包(在說了要用01揹包來做之後,這個分法是最直接能想到的),做法是同類物品拆成多個,例如s=10,分成1 1 1 1 1 1 1 1 1 1,通過其選與不選來表示出[0, si]中的所有情況,但此時複雜度為o(n * v * s),複雜度數量級達到109。考慮二進位制表示的方式,即用log(s)位數,就可以表示出[0, si]內任何數,例如s=10,只需要將物品分成1 2 4 3,通過對這幾份物品進行選與不選,就可以表示出[0, 10]內的所有數字,再例如s=20,可以分成1 2 4 8 5。因此二進位制表示的方式將複雜度優化為o(n * v * log(s))
值得學習的地方在於這種二進位制表示法,本質上可以用其它分法,只要能表示出[0, s]即可,但這種分法符合直覺,並且log的複雜度也會很低
#include using namespace std;
typedef pairpii;
const int n = 2010;
int n, v, f[n];
vectorobj;
// 轉化為樸素01揹包:同種多件物品拆解成1 1 1 1...,複雜度o(n)
// 轉化為二進位制01揹包:同種多件物品拆解成1 2 4... 餘數,複雜度o(logn)
// 本質都是01揹包,但拆解的方法可以表示[0, si]內的所有數字即可
// by yxc
int main()
if (s) obj.emplace_back(a*s, b*s);
}for (auto o : obj)
}printf("%d", f[v]);
}
AcWing 5 多重揹包問題 II
題目描述 有 n 種物品和乙個容量是 v的揹包。第 i種物品最多有 si 件,每件體積是 vi,價值是 wi。求解將哪些物品裝入揹包,可使物品體積總和不超過揹包容量,且價值總和最大。輸出最大價值。輸入格式 第一行兩個整數,n,v,用空格隔開,分別表示物品種數和揹包容積。接下來有 n行,每行三個整數 ...
ACWing 5 多重揹包問題 II
有n nn種物品和乙個容量是v vv的揹包。第i ii種物品最多有s is i si 件,每件體積是v iv i vi 價值是w iw i wi 求解將哪些物品裝入揹包,可使物品體積總和不超過揹包容量,且價值總和最大。輸出最大價值。輸入格式 第一行兩個整數,n nn,v vv,用空格隔開,分別表示物...
多重揹包問題 II
有 n 種物品和乙個容量是 v 的揹包。第 i 種物品最多有 si 件,每件體積是 vi,價值是 wi。求解將哪些物品裝入揹包,可使物品體積總和不超過揹包容量,且價值總和最大。輸出最大價值。輸入格式 第一行兩個整數,n,v,用空格隔開,分別表示物品種數和揹包容積。接下來有 n 行,每行三個整數 vi...