背包问题(贪心)& 二维01背包问题 Java

这篇具有很好参考价值的文章主要介绍了背包问题(贪心)& 二维01背包问题 Java。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

背包问题(贪心)

最优装载问题

题目描述

有n件物品和一个最大承重为w 的背包。第i件物品的重量是weight[i],每件只能用一次,求装入背包的最多物品数量。

题目分析

  • 因为我们只要求装入物品的数量,所以装重的显然没有装轻的划算
  • 因此将数组weight[i]按从小到大排序依次选择每个物品,直到装不下为止,就可以得到装入背包的最多物品数量。

代码

public static int stone(int n, int w, int[] weight) {
	Arrays.sort(weight);    //将weight数组从小到大排序
    int max = 0;
    int num = 0;
    for(int i = 0; i < n; i++) {
        if(max + weight[i] <= w){
        	max += weight[i];
            num += 1;
       }
    }
    return num;
}

01背包问题

与上面的贪心背包问题而言,贪心背包问题中物品的价值就是它的重量。
先前题主做的拿金币问题,也可以说是一道背包问题,不过其中背包的容量是无限的,物品就是金币。

题目描述

有n件物品和一个最大承重为bagweight 的背包。第i件物品的重量是weight[i],得到的价值是value[i] 。每件物品只能用一次,求解将哪些物品装入背包里物品价值总和最大。
卡码网第46题

题目分析

显然也是一道动态规划题,也就是说背包问题是动态规划问题的子集,当然这不重要。
我们先观察一下背包的属性:

  • 当前装入物品的个数
  • 当前装入物品的总重量(容量)
  • 当前装入物品的总价值
  • 关键在当前重量的基础上使得价值最高

注:下文基本转述于代码随想录的网站,只加了部分自己的理解

可转到代码随想录的网站去更深刻地理解01背包知识
代码随想录的链接:戳这里进入

老规矩动归五部曲

定义dp数组

定义一个二维数组dp[i][j],将i定义为当前放入了多少个物品,表示

  • 下标为[0-i]的物品里任意取,
  • 放进容量为j的背包
  • 价值总和最大是多少。(dp数组的值)

确定dp数组递归公式

在决定是否放入第i个物品时,显然有两种情况

  • 要么不满足放入第i个物品的情况(当物品i的重量大于背包j的重量时,物品i无法放进背包中)
dp[i][j] = dp[i-1][j];
  • 要么满足放入第i个物品的情况,此时比较放入前后的价值总和,判断是否要放入。
dp[i][j] = Math.max(dp[i-1][j], dp[i-1][j - weight[i] + value[i];

dp数组的初始化

从dp[i][j]出发,

  1. 当背包容量j为0的时候,则放不下任何物品,背包中价值总和为0;
for (int i = 0 ; i < weight.length; i++) { 
    dp[1][0] = 0;

再看其他情况。

  1. 因为递推公式dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]);
    当中含有i-1,即我们在遍历时肯定从i=1的时候开始遍历,那么物品为0的时候就一定要初始化。
    此时考虑是否可以加入物品0,
    • 当 j < weight[0]的时候,dp[0][j] 为 0
    • 当j >= weight[0]时,dp[0][j] 为value[0]
for (int j = 0 ; j < weight[0]; j++)   // 如果把dp数组预先初始化为0了,这一步可以省略
    dp[0][j] = 0;
    
for (int j = weight[0]; j <= bagweight; j++) 
    dp[0][j] = value[0];
  1. 其他位置可以任意初始化,但是一开始就统一把dp数组统一初始为0,更方便一些。

dp数组的遍历顺序

显然有两个遍历的维度:物品与背包容量
先遍历物品,或先遍历背包容量呢。
这里两种遍历顺序都可以,是因为,递推的方向分别是由上得到与由左得到,而两个遍历顺序都是会先得到递推公式需要的旧数据,因此不影响。文章来源地址https://www.toymoban.com/news/detail-798527.html

//先遍历物品
for(int i = 1; i < weight.size(); i++) { // 遍历物品
    for(int j = 0; j <= bagweight; j++) { // 遍历背包容量
        if (j < weight[i]) dp[i][j] = dp[i - 1][j];
        else dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]);

    }
}
//先遍历背包容量
for(int j = 0; j <= bagweight; j++) { // 遍历背包容量
    for(int i = 1; i < weight.size(); i++) { // 遍历物品
        if (j < weight[i]) dp[i][j] = dp[i - 1][j];
        else dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]);
    }
}

举例说明dp数组

代码

import java.util.Arrays;

public class BagProblem {
    public static void main(String[] args) {
        int[] weight = {1,3,4};//这里是代码随想录的示范用例
        int[] value = {15,20,30};
        int bagSize = 4;
        testWeightBagProblem(weight,value,bagSize);
    }

    public static void testWeightBagProblem(int[] weight, int[] value, int bagSize){

        // 创建dp数组
        int goods = weight.length;  // 获取物品的数量
        int[][] dp = new int[goods + 1][bagSize + 1];  // 给物品增加冗余维,i = 0 表示没有物品可选

        // 初始化dp数组,默认全为0即可
        // 填充dp数组
        for (int i = 1; i <= goods; i++) {
            for (int j = 1; j <= bagSize; j++) {
                if (j < weight[i - 1]) {  // i - 1 对应物品 i
                    /**
                     * 当前背包的容量都没有当前物品i大的时候,是不放物品i的
                     * 那么前i-1个物品能放下的最大价值就是当前情况的最大价值
                     */
                    dp[i][j] = dp[i - 1][j];
                } else {
                    /**
                     * 当前背包的容量可以放下物品i
                     * 那么此时分两种情况:
                     *    1、不放物品i
                     *    2、放物品i
                     * 比较这两种情况下,哪种背包中物品的最大价值最大
                     */
                    dp[i][j] = Math.max(dp[i - 1][j] , dp[i - 1][j - weight[i - 1]] + value[i - 1]);  // i - 1 对应物品 i
                }
            }
        }

        // 打印dp数组
        for(int[] arr : dp){
            System.out.println(Arrays.toString(arr));
        }
    }
}

到了这里,关于背包问题(贪心)& 二维01背包问题 Java的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 算法训练第四十二天|01背包问题 二维 、01背包问题 一维、416. 分割等和子集

    视频链接:https://www.bilibili.com/video/BV1cg411g7Y6/ 参考:https://programmercarl.com/%E8%83%8C%E5%8C%85%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%8001%E8%83%8C%E5%8C%85-1.html 对于面试的话,其实掌握01背包,和完全背包,就够用了,最多可以再来一个多重背包。 而完全背包又是也是01背包稍作变化而来,即:完全

    2024年02月01日
    浏览(44)
  • 【Java实现】动态规划算法解决01背包问题

    1、问题描述: 一个旅行者有一个最多能装m公斤的背包,现在有n中物品,每件的重量分别是W1、W2、……、Wn,每件物品的价值分别为C1、C2、……、Cn, 需要将物品放入背包中,要怎么样放才能保证背包中物品的总价值最大? 2、动态规划算法的概述 1)动态规划(Dynamic Progra

    2023年04月09日
    浏览(53)
  • 从二维数组到一维数组——探索01背包问题的动态规划优化

    本文将继续上一篇博客爬楼梯之后继续讲解同样用到了动态规划的 01背包问题 在解决动态规划问题时,我们经常面临着空间复杂度的挑战。01背包问题是一个典型的例子,通常使用二维数组来表示状态转移,但这样会带来额外的空间开销。在本文中,我们将探讨如何通过优化

    2024年04月11日
    浏览(58)
  • 【冲刺蓝桥杯-真题训练】递增三元组、回文日期、01背包问题、 数组切分

    🍎 博客主页:🌙@披星戴月的贾维斯 🍎 欢迎关注:👍点赞🍃收藏🔥留言 🍇系列专栏:🌙 蓝桥杯 🌙请不要相信胜利就像山坡上的蒲公英一样唾手可得,但是请相信,世界上总有一些美好值得我们全力以赴,哪怕粉身碎骨!🌙 🍉一起加油,去追寻、去成为更好的自己!

    2024年01月17日
    浏览(45)
  • 蓝桥杯备赛day02 -- 算法训练题 拿金币Java

    目录 题目: 问题描述 输入格式 输出格式 解题过程 第一步 定义dp数组 第二步 确定 dp 数组递推公式  第三步 dp数组的初始化 第四步 dp数组的遍历顺序 第五步 举例说明  报错:内存超限 用dp数组去存储位置上的金币 dp数组从二维降为一维  收获:   有一个N x N的方格,每一个

    2024年01月17日
    浏览(43)
  • 01背包(动态规划,贪心算法,回溯法,分支限界法)

    有n个物品,它们有各自的体积和价值,现有给定容量的背包,如何让背包里装入的物品具有最大的价值总和? number=4,capacity=8 物品编号(i) W(体积) V(价值) 1 2 3 2 3 4 3 4 5 4 5 6 1.什么是动态规划 1.动态规划算法是通过拆分问题,定义问题状态和状态之间的关系, 使得

    2024年02月08日
    浏览(68)
  • 【蓝桥杯备赛Java组】语言基础|竞赛常用库函数|输入输出|String的使用|常见的数学方法|大小写转换

    🎥 个人主页:深鱼~ 🔥收录专栏:蓝桥杯 🌄欢迎 👍点赞✍评论⭐收藏 目录 一、编程基础 1.1 Java类的创建  1.2 Java方法  1.3 输入输出  1.4 String的使用 二、竞赛常用库函数 1.常见的数学方法 2.大小写转换 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,

    2024年01月21日
    浏览(70)
  • 【蓝桥杯备赛Java组】第一章·语言基础|竞赛常用库函数|输入输出|String的使用|常见的数学方法|大小写转换

    🎥 个人主页:深鱼~ 🔥收录专栏:蓝桥杯 🌄欢迎 👍点赞✍评论⭐收藏 目录 一、编程基础 1.1 Java类的创建  1.2 Java方法  1.3 输入输出  1.4 String的使用 二、竞赛常用库函数 1.常见的数学方法 2.大小写转换 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,

    2024年01月19日
    浏览(72)
  • 动态规划(DP)---- 01背包入门详解----二维图是学会的关键

        动态规划,Dynamic Programing(简称DP),个人认为是一种 算法思想 , 用来解决多阶段多层次的选择问题,把一个复杂的问题分解成每个小块的子问题然后一个个解决来找到最优解。     DP适用 重叠子问题 和 最优子结构的性质 的问题。     DP问题范围分为 线性与非线性

    2024年02月03日
    浏览(38)
  • 蓝桥杯备赛之动态规划篇——涂色问题(区间DP)

    2023第十四届蓝桥杯模拟赛第二期个人题解(Java实现) 2023第十四届蓝桥杯模拟赛第三期个人题解(Java实现) 蓝桥杯备赛之动态规划篇——背包问题 蓝桥杯真题——单词分析(Java实现) 😘😘 哈喽,大家好!这里是蓝桥杯系列文章的动态规划章节🔥🔥,今天要讲解的是区

    2024年01月23日
    浏览(48)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包