背包问题Java详解版

本文详细介绍了背包问题的Java解法,包括01背包和完全背包问题。通过引用B站的背包九讲视频资源和ACwing的训练题目,讨论了未优化的解法及其O(n³)的时间复杂度问题。为了优化算法,文章提出了O(n²)时间复杂度的解决方案,并解释了优化原理,展示了如何从三个嵌套循环简化为两个。此外,还涉及了空间优化,将二维动态规划数组改为一维,利用倒序遍历来保留上一层的最优解,从而节省空间。
摘要由CSDN通过智能技术生成

资料:B站背包九讲:https://www.bilibili.com/video/BV1qt411Z7nE
对应训练题:https://www.acwing.com/problem/

01背包问题

在这里插入图片描述
此问题解法来自背包九讲,

未优化

状态:f[i][j]表示前 i 个物品,总体积为 j 的最大价值

所以就有两种方式,选当前物品放入背包和不选当前物品放入背包

即不选当前物品放入背包 :f[i-1][j],直接拿上一个物品的价值即可,体积不变

或者选当前物品放入背包,:f[i-1][j-v[i]]+w[i],需要减去当前物品的体积 再加上当前物品价值

当前i,j即取二者最大值

状态转移:f[i][j] = Math.max(f[i-1][j],f[i-1][j-v[j]]+w[i])

初始条件,f[0][0]=0

具体代码



public class Main {
   
 public static void main(String[] args) {
   
        Scanner sc = new Scanner(System.in);
        int N = sc.nextInt();
        int M = sc.nextInt();
        int[] Value = new int[N+1];
        int[] Weight = new int[N+1];
        //从1开始,0代表背包内容为0时的最大价值
        for(int i = 1;i<=N;i++){
   
            Weight[i] = sc.nextInt();
            Value[i] = sc.nextInt();
        }
        System.out.println(packageQuestion2(N,M,Weight,Value));

    }
    public static int packageQuestion(int N,int M,int[] Weight,int[] Value){
   
        // dp状态方程
        int[][] dp = new int[N+1][M+1];
        // dp[i][j]表示前i个物品,体积是j的,最大的总价值
        //遍历所有物品
        for(int i = 1;i<=N;i++){
   
            // 从0开始遍历背包容量
            for(int j = 0;j<=M;j++){
   
              //  dp[i][j]表示前i个物品,体积是j的,最大的总价值
                //如果当前背包容量大于等于当前元素的体积,就可以装
                if(j>=Weight[i]){
   
                    //dp[i-1][j]表示不选当前元素,表示当前容量下前i个元素的价值等于第i-1个元素的价值
                    //dp[i-1][j-Weight[i]]+Value[i]表示选择当前元素,即:当前元素针对当前背包大小的价值等于(背包现容量
                    //-当前元素的体积)的价值加上当前元素的价值,
                    //这里dp[i-1][j-Weight[i]]+Value[i],为啥要用i-1的原因是,如果用当前i,其实算当前i的时候已经对当前元素进行处理了,
                    //如果用i,会处理两次,用i-1才是处理针对当前层的上一层的最优
                    //上面是通俗一点的解释,真正的解释是:dp状态转移方程 都是由上一层来递推到当前层而不是直接在当前层上处理当前层的信息
                    dp[i][j] 
  • 2
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值