0-1背包理论基础详解

news2024/9/25 22:38:25

0-1背包问题:有 n 种物品,每种物品只有1个,求解将哪些物品装入背包里物品价值总和最大。

image.png
图片来自:代码随想录

0-1背包问题举例:

题目描述:

image.png

使用二维dp数组解决背包问题

动规五部曲:

  1. dp[i][j]: [0,i] 0~i 之间物品任取放入容量为 j 的背包
  • 不放物品 i:dp[i-1][j] 不放物品 i,就是从0~(i-1)
  • 放物品 i:dp[i-1][j - weight[i]] + value[i] 如果放物品 i,则需要从背包中减掉物品 i 的重量,然后再加上物品 i 的价值
    • 解释:dp[i-1][j - weight[i]] : 表示背包中不放物品 i ,并且背包的容量减去物品 i 的重量后,此时背包所能放的最大价值。
    • 此时再加上 物品 i 的重量,则此时背包的最大价值为在刚才的基础之上再加上 value[i]。
  1. 根据不放物品和放物品的情况,则递推公式为:dp[i][j]=Math.max(dp[i-1][j] , dp[i-1][j - weight[i]] + value[i])
  2. 初始化:初始化第一行和第一列,dp[0][0]=
  3. 遍历顺序:一般是有2层for循环,一层遍历背包,一层遍历物品,有时候for循环
    对于dp数组是二维数组时,即2层for循环的0-1背包问题,则2层for循环遍历顺序是可以颠倒的!
    但是对于一维dp数组,即滚动数组,情况需另行分析。

1.1、使用一维dp数组解决背包问题

代码实现:

package bag_problem;

import java.util.Arrays;

/**
 * @author: Arbicoral
 * @Description: 二维dp数组实现 0-1背包问题
 */
public class Bag01 {
    public static void main(String[] args) {
        int n = 3;// 共有 3个物品
        int bagSize = 4;// 背包的最大重量是 4
        int[] weight = new int[]{1, 3, 4};// 物品重量
        int[] value = new int[]{15, 20, 30};// 物品价值
        bagProblemSolution(n, bagSize, weight, value);
    }

    private static void bagProblemSolution(int n, int bagSize, int[] weight, int[] value) {
        // 1. 定义dp[][]
        int[][] dp = new int[n][bagSize + 1];
        // 2. 初始化dp[][]
        // 初始化第一列为 0 ,默认都是 0
        // 初始化第一行
        for (int i = 1; i <= bagSize; i++) {
            if (i >= weight[0]) {
                dp[0][i] = value[0];
            }
        }
        // 打印初始化后的dp数组
        System.out.println("打印初始化后的dp数组:");
        for (int[] i : dp) {
            System.out.println(Arrays.toString(i));
        }
        // 3. 遍历:填充dp[][]
        for (int i = 1; i < n; i++) {// 放置物品的个数
            for (int j = 1; j <= bagSize; j++) {// 遍历 背包
                if (j < weight[i]) {
                    // 如果背包的容量 < 物品i的重量,则dp[i][j]和上面的保持一致
                    dp[i][j] = dp[i - 1][j];
                } else {
                    // 如果背包的容量 >= 物品i的重量,按照递推公式即可
                    dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]);
                    // System.out.println("dp[" + i + "][" + j + "] = " + dp[i][j]);
                }
            }
        }
        System.out.println("--------------");
        // 打印dp数组
        System.out.println("填充后的dp数组:");
        for (int[] i : dp) {
            System.out.println(Arrays.toString(i));
        }
    }
}

输出结果:

image.png

1.2、使用一维dp数组解决背包问题

本质:将二维dp数组降为一维dp数组,每次将二维dp数组的行复制后再更新复制后的行。(可能有点绕)

动规五部曲:

  1. dp[j] : 背包为 j 的容量最多能装的物品价值;
  2. 递推公式:dp[j]=Math.max(dp[j],dp[j - weight[i]] + value[i]) 不放物品 i :dp[j] 放物品 i :dp[j - weight[i]] + value[i]
  3. 初始化:dp[0]=0; dp[1]=
  4. 遍历顺序:倒序遍历,因为一维dp数组中是重复利用的,旧值和当前需要的值会有冲突;
    先遍历物品,再遍历背包。

代码实现:

package bag_problem;

import java.util.Arrays;

/**
 * @author: Arbicoral
 * @Description: 一维dp数组实现 0-1背包问题
 */
public class Bag01OneDimension {
    public static void main(String[] args) {
        int n = 3;// 共有 3个物品
        int bagSize = 4;// 背包的最大重量是 4
        int[] weight = new int[]{1, 3, 4};// 物品重量
        int[] value = new int[]{15, 20, 30};// 物品价值
        bagProblemOneDimensionSolution(n, bagSize, weight, value);
    }

    private static void bagProblemOneDimensionSolution(int n, int bagSize, int[] weight, int[] value) {
        // 1. 定义dp[]
        int[] dp = new int[bagSize + 1];
        // 2. 初始化dp[]
        // 初始化第一列为 0 ,默认都是 0
        // 打印初始化后的dp数组
        System.out.println("打印初始化后的dp数组:");
        System.out.println(Arrays.toString(dp));

        System.out.println("填充后的dp数组:");
        // 3. 遍历:填充dp[]
        for (int i = 0; i<n; i++) {
            for (int j = bagSize; j >= weight[i]; j--) {
                dp[j] = Math.max(dp[j], dp[j - weight[i]] + value[i]);
            }
            // 打印dp数组
            System.out.println(Arrays.toString(dp));
        }
    }
}

输出结果

image.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1074216.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

智能工厂MES系统,终端设备支持手机、PDA、工业平板、PC

一、开源项目简介 源计划智能工厂MES系统(开源版) 功能包括销售管理&#xff0c;仓库管理&#xff0c;生产管理&#xff0c;质量管理&#xff0c;设备管理&#xff0c;条码追溯&#xff0c;财务管理&#xff0c;系统集成&#xff0c;移动端APP。 二、开源协议 使用GPL-3.0开…

【python海洋专题十四】读取多个盐度nc数据画盐度季节变化图

本期内容 读取多个盐度文件&#xff1b;拼接数据在画盐度的季节分布图Part01. 使用数据 IAP 网格盐度数据集 数据详细介绍&#xff1a; 见文件附件&#xff1a; pages/file/dl?fid378649712527544320 全球温盐格点数据.pdf IAP_Global_ocean_gridded_product.pdf 全球温…

Android多线程学习:线程池(一)

一、概念 线程池&#xff1a;创建并维护一定数量的空闲线程&#xff0c;当有需要执行的任务&#xff0c;就交付给线程池中的一个线程&#xff0c;任务执行结束后&#xff0c;该线程也不会死亡&#xff0c;而是回到线程池中重新变为空闲状态。 线程池优点&#xff1a; 1、重用…

Linux系列---【查看mac地址】

查看mac地址命令 查看所有网卡命令 nmcli connection show 查看物理网卡mac地址 ifconfig 删除网卡 nmcli connection delete virbr0 禁用libvirtd.service systemctl disable libvirtd.service 启用libvirtd.service systemctl enable libvirtd.service

使用css 与 js 两种方式实现导航栏吸顶效果

position的属性我们一般认为有 position:absolute postion: relative position:static position:fixed position:inherit; position:initial; position:unset; 但是我最近发现了一个定位position:sticky 这个可以称为粘性定位。 这个粘性定位的元素会始终在那个位置 <st…

firefox的主题文件位置在哪?记录以防遗忘

这篇文章写点轻松的 最近找到了一个自己喜欢的firefox主题,很想把主题的背景图片找到,所以找了下主题文件所在位置 我的firefox版本:版本: 118.0.1 (64 位)主题名称: Sora Kawai 我的位置在 C:\Users\mizuhokaga\AppData\Roaming\Mozilla\Firefox\Profiles\w0e4e24v.default…

可视大盘 + 健康分机制,火山引擎 DataLeap 为企业降低资源优化门槛!

更多技术交流、求职机会&#xff0c;欢迎关注字节跳动数据平台微信公众号&#xff0c;回复【1】进入官方交流群 随着数仓及研发技术团队维护的数据量大、资源使用量大、成本越高、优化压力越大。如何主动发现无效或低效使用的资源&#xff0c;并且可以周期性高效的进行主动治理…

js 气泡上升和鼠标点击事件

效果图 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name"viewport" content"widthdevice-width, initial-scale1.0" /><title>Document</title><style>bod…

银河麒麟服务器x86安装ntp客户端,并配置成功可以同步时间

脚本 # 安装ntp客户端 sudo dnf install chrony # 配置 pool 2.centos.pool.ntp.org iburst给这一行加注释 sudo sed -i s/^pool 2.centos.pool.ntp.org iburst/#&/ /etc/chrony.conf # 添加3个阿里云NTP服务器 # echo -e "server ntp1.aliyun.com iburst\nserver nt…

安卓 kotlin-supportFragmentManager报红

如果你继承baseActivity 请查看 是不是继承 AppCompatActivity

全网都在找的python+requests接口自动化测试框架实例详解教程

前言 Python是一种功能强大的编程语言&#xff0c;它可以用于自动化测试&#xff0c;特别是接口自动化测试。许多Python库都可以用于接口自动化测试&#xff0c;其中requests库是其中最受欢迎的库之一。 requests库可以用于发送HTTP请求并获取服务器响应&#xff0c;从而轻松…

java案例21:学生管理系统

思路&#xff1a; 编写一个学生管理系统&#xff0c; 实现对学生信息的添加、删除、修改和查询功能。首页&#xff1a; 用于显示系统的所有操作&#xff0c;并根据用户在控制台的输入选择需要使用的功能查询功能&#xff1a; 用户选择后&#xff0c;在控制台打印所有学生信息添…

阿里云服务器公网带宽多少钱1M?

阿里云服务器公网带宽计费模式按固定带宽”计费多少钱1M&#xff1f;地域不同带宽价格不同&#xff0c;北京、杭州、深圳等大陆地域价格是23元/Mbps每月&#xff0c;中国香港1M带宽价格是30元一个月&#xff0c;美国硅谷是30元一个月&#xff0c;日本东京1M带宽是25元一个月&am…

爬虫Python

文章目录 基本数据类型bytes类型python数据类型转换 python运算符&#xff08;必会&#xff01;&#xff01;&#xff01;&#xff09;python数字数学函数&#xff08;必会&#xff01;&#xff01;&#xff01;&#xff09;随机数函数三角函数&#xff08;简&#xff09;数字常…

c++视觉处理---均值滤波

均值滤波 cv::blur()函数是OpenCV中用于应用均值滤波的函数。均值滤波是一种简单的平滑技术&#xff0c;它计算每个像素周围像素的平均值&#xff0c;并用该平均值替代原始像素值。这有助于降低图像中的噪声&#xff0c;并可以模糊图像的细节。 以下是cv::blur()函数的基本用…

记一次 .NET某账本软件 非托管泄露分析

一&#xff1a;背景 1. 讲故事 中秋国庆长假结束&#xff0c;哈哈&#xff0c;在老家拍了很多的短视频&#xff0c;有兴趣的可以上B站观看&#xff1a;https://space.bilibili.com/409524162 &#xff0c;今天继续给大家分享各种奇奇怪怪的.NET生产事故&#xff0c;希望能帮助…

c++视觉处理---高斯滤波

高斯滤波处理 高斯滤波是一种常用的平滑滤波方法&#xff0c;它使用高斯函数的权重来平滑图像。高斯滤波通常用于去除噪声并保留图像中的细节。在OpenCV中&#xff0c;可以使用cv::GaussianBlur()函数来应用高斯滤波。 以下是cv::GaussianBlur()函数的基本用法&#xff1a; …

区块链技术的飞跃: 2023年的数字革命

随着时代的推进和技术的不断创新&#xff0c;2023年成为区块链技术飞跃发展的一年。区块链&#xff0c;一个曾经只是数字货币领域的技术&#xff0c;现在已经逐渐渗透到各个行业&#xff0c;成为推动数字经济发展的重要力量。在这个数字革命的时代&#xff0c;我们探讨区块链技…

纸黄金效率太低不如做现货

如果从字面上的意义去理解&#xff0c;纸黄金就是在账面上交易的黄金&#xff0c;具体来说它是国内银行为客户提供的一种记账式的黄金买卖&#xff0c;交易的记录和买卖的盈亏值&#xff0c;都只会在预先开设的账户上体现&#xff0c;投资过程中不涉及实物黄金的交收。 对于追求…

Docker基础(CentOS 7)

参考资料 hub.docker.com 查看docker官方仓库&#xff0c;需要梯子 Docker命令大全 黑马程序员docker实操教程 &#xff08;黑马讲的真的不错 容器与虚拟机 安装 yum install -y docker Docker服务命令 启动服务 systemctl start docker停止服务 systemctl stop docker重启…