多重背包问题,小白也可以看懂,哦耶~

多重背包问题

问题描述

有N种物品和一个容量是V的背包
第i种物品最多有s件,每件体积是v,价值是w
求解将哪些物品装入背包,可使物品体积总和不超过背包容量,且价值总和最大
———————————————————————————————————————

解法一

问题分析:

最外层循环遍历每个商品
中间的循环可以遍历背包的体积
1.如果当前物品的体积大于背包的体积,说明背包装不下这个商品,那么就和装上一件物品的情况一样了,上一件物品是i - 1,所以代码是

dp[i][j] = dp[i - 1][j]

2.如果当前背包的体积大于物品的体积,这个物品可以装下,那么之后要考虑的问题就是装几件了,
首先这几件物品的总体积不能超过背包的总体积,第二是总件数不能超过题目所规定的s[i - 1]
对应的代码为:

for(int k = 0; j - k * v[i - 1] >= 0 && k < s[i - 1]; k++)

dp[i][j]的意思是之前装0~k件中的最大值
dp[i - 1][j - k * v[i - 1]] + k * w[i - 1] 是装k件的值
i - 1的意思是,当前所装的k件i物品,是在第i - 1种物品的基础上装的
j - k * v[i - 1]的意思是,背包需要腾出来k * v[i - 1]的空间用来装这几件
k * w[i - 1] 的意思是这几件的价值

dp[i][j] = Math.max(dp[i][j], dp[i - 1][j - k * v[i - 1]] + k * w[i - 1]);
public class Main {

    int N;   //物品的种数为N
    int V;   //背包的容量为V

    //v是第i种商品的体积   w是第i种商品的价值   s是第i种商品的个数
    public int doubleBag1(int[] v, int[] w, int[] s){
        int[][] dp = new int[N + 1][V + 1];
        for(int i = 1; i <= N; i++){     //确定是第几个商品
            for(int j = 1; j <= V; j++){ //确定体积
                if (v[i - 1] > j) dp[i][j] = dp[i - 1][j];
                else{

                    //确定商品个数
                    for(int k = 0; j - k * v[i - 1] >= 0 && k < s[i - 1]; k++){
                        dp[i][j] = Math.max(dp[i][j], dp[i - 1][j - k * v[i - 1]] + k * w[i - 1]);
                    }
                }
            }
        }
        return dp[N][V];
    }
}

———————————————————————————————————————

解法二

题目分析:

由题目可以知道有有N种物品和一个容量是V的背包,第i种物品最多有s件,每件体积是v,价值是w
如果我们将物品的体积和价值输入v和w数组的时候,不是按种来输入,而是按照件数来输入,就是把N种物品里的每一件都输入进去,那么不是可以转化成0-1背包问题嘛


代码分析:

这里就和0-1背包一样了
大家可以看 最详细的0-1背包问题,小白也可以看懂哦

public class Main {

    int N;   //物品的种数为N
    int V;   //背包的容量为V

    //基于0-1背包的解法
    //v是第i件商品的体积
    //w是第i件商品的价值
    public int doubleBag2(int[] v, int[] w){
    	//v.length就是商品的总件数啦
        int[][] dp = new int[v.length + 1][V + 1];
        for(int i = 1; i <= v.length; i++){
            for(int j = V; j > 0; j--) {
                if (v[i - 1] > j) dp[i][j] = dp[i - 1][j];
                else dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - v[i - 1]] + w[i - 1]);
            }
        }

        return dp[v.length + 1][V + 1];
    }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值