有N
种物品和一个容量为W
的背包, 第i
种物品最多有nums[i]
件可用 ,每件重量是weight[i]
,价值是value[i]
。求解将哪些物品装入背包可使得这些物品的重量和不超过背包的容量,且价值总和最大。
输入:N = 4, W = 5, weight = [1,2,3,4], value = [2,4,4,5], nums = [3,1,3,2]
输出:10
解题思路
仔细观察题目,会发现多重背包与
其实将多重背包里面的每种物品展开就是01背包问题了。比如有s
个物品a
,那么就可以展开成a1,a2,...as
,然后再用01背包的方法解决。或者把每种商品遍历的个数放在01背包里面再遍历一遍。
C++
// 方法一:将每种物品展开 class Solution { public: int multipleBackpake(vector<int> weight, vector<int> value, vector<int> nums, int bagsize) { // 将每种物品展开 for (int i = 0; i < nums.size(); i++) { while (nums[i] > 1) { weight.push_back(weight[i]); value.push_back(value[i]); nums[i]--; } } vector<int> dp(bagsize + 1, 0); for (int i = 0; i < weight.size(); i++) { //先遍历物品 for (int j = bagsize; j >= weight[i]; j--) { //再倒序遍历背包 dp[j] = max(dp[j], dp[j - weight[i]] + value[i]); } } return dp[bagsize]; } }; //方法二:把每种商品遍历的个数放在01背包里面再遍历一遍 class Solution1 { public: int multipleBackpake(vector<int> weight, vector<int> value, vector<int> nums, int bagsize) { vector<int> dp(bagsize + 1, 0); for (int i = 0; i < weight.size(); i++) { //遍历物品 for (int j = bagsize; j >= weight[i]; j--) { //遍历背包 for (int k = 1; k <= nums[i] && j >= k * weight[i]; k++) { //物品数量,注意k是从1开始的 dp[j] = max(dp[j], dp[j - k * weight[i]] + k * value[i]); } } } return dp[bagsize]; } };
JavaScript
/** * @param {number[]} weight * @param {number[]} value * @param {number[]} nums * @param {number} bagsize */ function multipleBackpake(weight, value, nums, bagsize) { const dp = new Array(bagsize + 1).fill(0); for (let i = 0; i < weight.length; i++) { //先遍历物品 for (let j = bagsize; j >= weight[i]; j--) { //再倒序遍历背包 for (let k = 1; k <= nums[i] && j >= k * weight[i]; k++) { dp[j] = Math.max(dp[j], dp[j - k * weight[i]] + k * value[i]); } } } return dp[bagsize]; }