acwing 5 多重揹包問題 II

2022-10-08 21:48:26 字數 1367 閱讀 4963

有 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...