首页 > 试题广场 >

完全背包

[编程题]完全背包
  • 热度指数:3155 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解
你有一个背包,最多能容纳的体积是V。

现在有n种物品,每种物品有任意多个,第i种物品的体积为v_i ,价值为w_i

(1)求这个背包至多能装多大价值的物品?
(2)若背包恰好装满,求至多能装多大价值的物品?

数据范围:
示例1

输入

6,2,[[5,10],[3,1]]

输出

[10,2]
示例2

输入

8,3,[[3,10],[9,1],[10,1]]

输出

[20,0]

说明

无法恰好装满背包。 
示例3

输入

13,6,[[13,189],[17,360],[19,870],[14,184],[6,298],[16,242]]

输出

[596,189]

说明

可以装5号物品2个,达到最大价值298*2=596,若要求恰好装满,只能装1个1号物品,价值为189. 
python版本简单解法,只需要维护一个dp数组就好。
加一个判断条件,判断如果当前位置dp[i] = 0(没有放物品),则不进行累计。
class Solution:
    def knapsack(self , v: int, n: int, nums: List[List[int]]) -> List[int]:
        dp = [0]*(v+1)
        for i in range(n):
            for j in range(0, v - nums[i][0]+1): # 完全背包问题,正向遍历容量
                if dp[j] != 0&nbs***bsp;j == 0:
                    dp[j+ nums[i][0]] = max(dp[j+ nums[i][0]], dp[j] + nums[i][1])
        return [max(dp), dp[v]]


发表于 2023-03-19 16:38:55 回复(0)

cpp,完全背包模板

class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param v int整型 
     * @param n int整型 
     * @param nums int整型vector<vector<>> 
     * @return int整型vector
     */
    vector<int> knapsack(int v, int n, vector<vector<int> >& nums) {
        // write code here
        vector<int> dp1(v + 1, 0), dp2(v + 1, -1);
        dp2[0] = 0;

        for (int i = 0; i < n; ++i) {
            for (int j = nums[i][0]; j <= v; ++j) {
                dp1[j] = max(dp1[j], dp1[j - nums[i][0]] + nums[i][1]);
                if (dp2[j - nums[i][0]] >= 0) {
                    dp2[j] = max(dp2[j], dp2[j - nums[i][0]] + nums[i][1]);
                }
            }
        }

        int res1 = dp1[v];
        int res2 = dp2[v] >= 0 ? dp2[v] : 0;

        return {res1, res2};
    }
};
发表于 2022-08-18 09:36:26 回复(0)
func knapsack( v int ,  n int ,  nums [][]int ) []int {
    dp,dp1 := make([]int, v + 1),  make([]int, v + 1)
    for tmpV := 1; tmpV <= v; tmpV++ { // 遍历容量v作为状态复用
        max, max1 := 0, 0
        for i := 1; i <= len(nums);i++ {
            iv := nums[i - 1][0]
            iw := nums[i - 1][1]

            if tmpV >= iv {
                // 1. 放入第i种物品刚好得到最大价值
                if max < dp[tmpV - iv] +iw { 
                    max = dp[tmpV - iv] +iw
                }
                //2 第j种物品刚好填满i个容量 得到最大价值
                if (tmpV - iv == 0 || dp1[tmpV - iv] != 0) && max1 < dp1[tmpV - iv] + iw { 
                    max1 = dp1[tmpV - iv] + iw
                }
            } 
        }
        dp[tmpV], dp1[tmpV] = max, max1
    }
    return []int{dp[v], dp1[v]}
}
发表于 2023-07-20 22:10:00 回复(0)
import java.util.*;


public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param v int整型 
     * @param n int整型 
     * @param nums int整型ArrayList<ArrayList<>> 
     * @return int整型ArrayList
     */
    public ArrayList<Integer> knapsack (int v, int n, ArrayList<ArrayList<Integer>> nums) {
        // write code here
        ArrayList<Integer> al = new ArrayList<Integer> ();
        int[] dp = new int[v+1];
        int[] dpl = new int[v+1];
        dp[0] = 0;
        Arrays.fill(dpl,Integer.MIN_VALUE);
        dpl[0] = 0;
        for(int curHeave = 1;curHeave <= v;curHeave++){
            for(int i = 0;i<n;i++){
                int k = curHeave  - nums.get(i).get(0);
                if(k < 0) continue;
                else{
                if(dpl[k] == Integer.MIN_VALUE);
                else{dpl[curHeave] = Math.max(dpl[curHeave],dpl[k]+nums.get(i).get(1));}
                dp[curHeave] = Math.max(dp[curHeave],dp[k]+nums.get(i).get(1));
                }
                
            }
        }
        al.add(dp[v]);
       if(dpl[v] == Integer.MIN_VALUE){
           al.add(0);
       }else{
           al.add(dpl[v]);
       }
        return al;
    }
}
发表于 2022-05-06 15:53:52 回复(0)