【动态规划算法(dp算法)】之背包问题

news2025/1/20 3:41:52

文章目录

      • 背包问题
        • 动规五部曲
        • 一、0-1背包问题 :限制物品不可重复 (要么不选 要么选一个)
        • 二、完全背包问题:不限制重复(要么不选 要么可以多选)(完全背包可以转化为0-1背包问题)
      • 动态规划:01背包 二维dp数组
      • 动态规划:01背包滚动数组
      • 动规五部曲分析如下:
      • 动态规划代码

背包问题

在这里插入图片描述

动规五部曲

其中最主要的就是前两个步骤

  • 确定dp数组以及下标的含义
  • 确定递推公式
  • dp数组如何初始化
  • 遍历顺序
  • 出结论,写代码
一、0-1背包问题 :限制物品不可重复 (要么不选 要么选一个)
二、完全背包问题:不限制重复(要么不选 要么可以多选)(完全背包可以转化为0-1背包问题)

下面讲的是0-1背包问题:

其中:

  • i,表示物品;j表示背包容量;
  • w[] 数组表示物品重量的集合;
  • v[] 数组表示物品价值的集合;
  • v[][]表示装入背包的最大价值集合;

(1)找w[i]和j的关系

v[i][0]=v[0][j]=0,表示第一列和第一行最大价值都是0;

  • 1.w[i]>j,表示当前准备新增物品的质量要是大于背包的容量,v[i][j] =v[i-1][j],该位置的最大价值就是把该列上一行的数据赋给它;如第二次音响进来的最大价值情况;v[i-1][j]上一个单元格装入的最大价值;
  • 2.j>=w[i],表示背包的容量要是大于等于当前要新增物品的质量;

(2) 则装入的最大价值策略为v[i][j] = max { v[i-1][j], v[i] + v[i-1][j-w[i]] }
v[i] 当前商品的价值;
j-w[i] 装入当前物品后,背包剩余的容量大小;

(3) v[i] + v[i-1][j-w[i]]表示:装入当前物品的价值 + 剩余容量可装入的最大价值
最后比较 两个最大价值,取max

eg:总w=4;电脑w=3装入后的价值2000 + 剩余w=1只可装一个吉他价值1500=3500 > 上一个单元格装入的最大价值3000
所以选择这个装配方式;

上面讲的很清楚了 看一下具体的实现

那么可以有两个方向推出来dp[i][j]:

1.不放物品idp[i][j]=dp[i - 1][j]
w[i]>j,表示:当前准备新增物品的质量要是大于背包的容量,v[i][j] =v[i-1][j]
就是当物品i的重量大于背包j的重量时,物品i无法放进背包中,所以被背包内的价值依然和前面相同。

2.放物品i
表示背包的容量要是大于等于当前要新增物品的质量;

  • dp[i - 1][j - weight[i]]推出,
    dp[i - 1][j - weight[i]] 为背包容量为j - weight[i]的时候 不放物品i(所以是i-1)的最大价值
  • value[i]+dp[i - 1][j - weight[i]]
    表示:装入当前物品的价值 + 剩余容量可装入的最大价值

所以递归公式: dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]);

动态规划:01背包 二维dp数组

动规五部曲分析一波

  1. 确定dp数组以及下标的含义
- 对于背包问题,有一种写法, 是使用二维数组,即dp[i][j] 表示从下标为[0,i]的物品里任意取,放进容量为j的背包,价值总和最大是多少。
- w[i] 表示第i个物品的重量;
- v[i] 表示第i个物品的价值;

要时刻记着这个dp数组的含义,下面的一些步骤都围绕这dp数组的含义进行的,如果哪里看懵了,就来回顾一下i代表什么,j又代表什么。

  1. 确定递推公式
再回顾一下dp [i][j]的含义:从下标为[0-i]的物品里任意取,放进容量为j的背包,价值总和最大是多少。
# 那么可以有两个方向推出来dp[i][j]:
##1.不放物品i:dp[i][j]=dp[i - 1][j]。
------w[i]>j,表示当前准备新增物品的质量要是大于背包的容量,v[i][j] =v[i-1][j],
      就是当物品i的重量大于背包j的重量时,物品i无法放进背包中,所以被背包内的价值依然和前面相同。
##2.放物品i:
	  表示背包的容量要是大于等于当前要新增物品的质量;
	#  dp[i - 1][j - weight[i]]推出,
	dp[i - 1][j - weight[i]] 为背包容量为j - weight[i]的时候 不放物品i(所以是i-1)的最大价值,
	#  value[i]+dp[i - 1][j - weight[i]]  
    表示:装入当前物品的价值 + 剩余容量可装入的最大价值

所以递归公式: dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]);

动态规划:01背包滚动数组

读到这里估计大家都忘了 dp[i][j]里的ij表达的是什么了,i是物品,j是背包容量。

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

动规五部曲分析如下:

  1. 确定dp数组的定义

    在一维dp数组中,dp[j]表示:容量为j的背包,所背的物品价值可以最大为dp[j]

  2. 一维dp数组的递推公式

  • dp[j]可以通过dp[j - weight[i]]推导出来
    dp[j - weight[i]]表示容量为j - weight[i]的背包所背的最大价值。
    dp[j - weight[i]] + value[i] 表示:容量为 j-物品i重量的背包的价值 加上 物品i的价值。
    (就是容量为j的背包,放入物品i了之后的价值再加上物品i的价值)
  • 此时dp[j]有两个选择
    一个是取自己dp[j] 相当于二维dp数组中的dp[i-1][j],即不放物品i;
    一个是取dp[j - weight[i]] + value[i],即放物品i,指定是取最大的,毕竟是求最大价值,
  • 所以递归公式为:
    dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);
  1. 一维dp数组如何初始化

dp[j]表示:容量为j的背包,所背的物品价值可以最大为dp[j],那么背包容量为0所背的物品的最大价值就是0。

所以dp[0]=0

假设物品价值都是大于0的,所以dp数组初始化的时候,都初始为0就可以了。

Arrays.fill(dp,0);
  1. 遍历顺序从后向前

​ 还是先遍历物品,然后再遍历背包容量

for(int i = 0; i < v.length; i++) { // 遍历物品
    for(int j = weight; j >= w[i]; j--) { // 遍历背包容量
        dp[j] = max(dp[j], dp[j - w[i]] + v[i]);
    }
}

动态规划代码

  1. 代码
public static void main(String[] args) {
        int[] v = {15, 20, 30};
        int[] w = {1, 3, 4};
        int weight = 4;
        int[] dp = new int[weight + 1];
        Arrays.fill(dp, 0);
        //i是物品 j是背包重量 所以物品重量是w[i]
        int res=dp[0];
        for (int i = 0; i < v.length; i++) {
            for (int j = weight; j >= w[i]; j--) {
                dp[j]=Math.max(dp[j],dp[j-w[i]]+v[i]);
                res=Math.max(res,dp[j]);
            }
        }
        System.out.println(res);
    }
public static void main(String[] args) {
        int[] value = new int[]{1500, 2000, 3000};//表示物品的价值
        int[] weight = {1, 4, 3};//表示物品的重量
        int w = 4;//背包的容量
        int n = value.length;//物品的个数
        //创建一个二维数组 表 n+1行:有一行是0行;w+1列:有一列是0列
        int[][] dp = new int[n + 1][w + 1];  //n+1就是列长 w+1就是行长
        //1.初始化第一行第一列
        for (int i = 0; i < w + 1; i++) {
            dp[0][i] = 0;//第一行为0
        }
        for (int i = 0; i < n + 1; i++) {
            dp[i][0] = 0;//第一列为0
        }
        int res=dp[0][0];
        //2.判断物品重量w[i] 和背包容量的关系
        for (int i = 1; i < dp.length; i++) {//从第一行
            for (int j = 1; j < dp[0].length; j++) {//第一列开始
                if (weight[i-1] > j) {//i-1是因为我们从1开始的
                    dp[i][j] = dp[i - 1][j];
                } else {
                    dp[i][j] = Math.max(dp[i - 1][j], (value[i-1] + dp[i - 1][j - weight[i-1]]));
                    //value[i-1] //是因为我们的i是从1开始的 所以-1
                    //weight[i-1]
                }
                res=Math.max(res,dp[i][j]);
            }
        }
//        3.打印这个最大价值表
        for (int i = 0; i <dp.length ; i++) {
            for (int j = 0; j <dp[0].length; j++) {
                System.out.print(dp[i][j]+"\t");
            }
            System.out.println();
        }
        System.out.println("最大价值为:"+res);
    }
}

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

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

相关文章

宝塔面板 -- 创建第一个自己的网站

文章目录 前言 一、安装宝塔面板 二、注册宝塔面板 三、安装nginx 四、第一个hello world运行 五、总结 文章目录 前言一、安装宝塔面板二、注册宝塔面板三、安装nginx四、第一个hello world运行五、总结 前言 阿里云最近对在校大学生免费每人赠送一台服务器&#xff0c…

Apache ShenYu 网关JWT认证绕过漏洞 CVE-2021-37580

Apache ShenYu 网关JWT认证绕过漏洞 CVE-2021-37580 已亲自复现 漏洞名称漏洞描述影响版本 漏洞复现环境搭建漏洞利用 修复建议总结 Apache ShenYu 网关JWT认证绕过漏洞 CVE-2021-37580 已亲自复现) 漏洞名称 漏洞描述 Apache ShenYu是一个异步的&#xff0c;高性能的&#x…

第九周算法题(哈希映射,二分,Floyd算法 (含详细讲解) )

第九周算法题 第一题 题目来源&#xff1a;33. 搜索旋转排序数组 - 力扣&#xff08;LeetCode&#xff09; 题目描述&#xff1a;整数数组 nums 按升序排列&#xff0c;数组中的值 互不相同 。 在传递给函数之前&#xff0c;nums 在预先未知的某个下标 k&#xff08;0 <…

HA启动Advanced SSH Web Terminal 提示附加组件似乎尚未准备就绪,它可能仍在启动。是否要再试一次?

环境&#xff1a; Home Assistant OS11.1 Advanced SSH & Web Terminal 17.0 问题描述&#xff1a; HA安装好SSH加载项&#xff0c;启动Advanced SSH & Web Terminal 提示附加组件似乎尚未准备就绪&#xff0c;它可能仍在启动。是否要再试一次&#xff1f; 解决方案…

尚硅谷 java 2023(基础语法)笔记

一、变量与运算符 1、HelloWorld的编写和执行 class HelloChina{public static void main(String[] args){System.out.println("hello,world!!你好&#xff0c;中国&#xff01;");} } 总结&#xff1a; 1. Java程序编写和执行的过程&#xff1a; 步骤1&#xff1…

解决 MATLAB 遗传算法中 exitflg=4 的问题

一、优化问题简介 以求解下述优化问题为例&#xff1a; P 1 : min ⁡ p ∑ k 1 K p k s . t . { ∑ k 1 K R k r e q l o g ( 1 α k ∗ p k ) ≤ B b s , ∀ k ∈ K p k ≥ 0 , ∀ k ∈ K \begin{align} {P_1:}&\mathop{\min}_{\bm{p}}{ \sum\limits_{k1}^K p_k } \no…

微软写了份GPT-4V说明书:166页讲解又全又详细demo示例一应俱全

原文&#xff1a;微软写了份GPT-4V说明书&#xff1a;166页讲解又全又详细demo示例一应俱全 - 哔哩哔哩 编者按&#xff1a;这篇文章深入研究了GPT-4V的用法、基本功能&#xff0c;用较大篇幅介绍了GPT-4V在遵循文字说明、视觉指向和视觉参考提示、视觉文本提示等方面展示出的…

Swiper轮播图系列

一、初始化Swiper new Swiper(.swiper-container, {initialSlide: 0,slidesPerView: 3,breakpoints: {750: {slidesPerView: 1},990: {slidesPerView: 2}},spaceBetween: 12,loop: true,speed: 1000,autoplay: {disableOnInteraction: false, // 手动滑动后&#xff0c;不停止…

阿里云 ACK One 新特性:多集群网关,帮您快速构建同城容灾系统

云布道师 近日&#xff0c;阿里云分布式云容器平台 ACK One[1]发布“多集群网关”[2]&#xff08;ACK One Multi-cluster Gateways&#xff09;新特性&#xff0c;这是 ACK One 面向多云、多集群场景提供的云原生网关&#xff0c;用于对多集群南北向流量进行统一管理。 基于 …

【UML】第9篇 类图(概念、作用和抽象类)(1/3)

目录 一、类图的概念 二、类图的主要作用 三、类图的构成 3.1 类的名称 3.2 抽象类&#xff08;Abstract Class&#xff09; 一、类图的概念 类图是UML模型中静态视图。它用来描述系统中的有意义的概念&#xff0c;包括具体的概念、抽象的概念、实现方面的概念等。静态视…

Pytorch项目,肺癌检测项目之四

# 安装图像处理 的两个包 simpleITK 和 ipyvolume # 安装缓存相关的两个包 diskcache 和 cassandra-driver import gzip from diskcache import FanoutCache, Disk from cassandra.cqltypes import BytesType from diskcache import FanoutCache,Disk,core from diskcache…

浏览器原理篇—渲染优化

渲染优化 通常一个页面有三个阶段&#xff1a;加载阶段、交互阶段和关闭阶段 加载阶段&#xff0c;是指从发出请求到渲染出完整页面的过程&#xff0c;影响到这个阶段的主要因素有网络和 JavaScript 脚本。交互阶段&#xff0c;主要是从页面加载完成到用户交互的整合过程&…

【星海出品】Keepalived 使用基础案例 (二)

keepalived 使用 [rootmaster ~]# cat /etc/keepalived/keepalived.conf ! Configuration File for keepalivedglobal_defs { //全局配置notification_email { //定义报警收件人邮件地址acassenfirewall.locfailoverfirewall.locsysadminfirewall.loc}notification_…

单例模式实现

⭐ 作者&#xff1a;小胡_不糊涂 &#x1f331; 作者主页&#xff1a;小胡_不糊涂的个人主页 &#x1f4c0; 收录专栏&#xff1a;JavaEE &#x1f496; 持续更文&#xff0c;关注博主少走弯路&#xff0c;谢谢大家支持 &#x1f496; 单例模式 1. 什么是单例模式2. 饿汉模式3.…

JoySSL诚招SSL证书代理

不久前&#xff0c;阿里云宣布了一个让人稍感唏嘘的消息——它们的一年期免费SSL证书服务将停步&#xff0c;转而提供三个月期限的证书。这一变化&#xff0c;无疑会使得网站开发的公司在维持用户信任和网站安全上多出心思。然而&#xff0c;免费的午餐并没有彻底消失&#xff…

Epson打印机连接wifi

环境 Epson L3153 打印机联通无线光猫 背景 最近家里的联通宽带不太稳定&#xff0c;经常断网。今天打了联通客服电话&#xff0c;师傅上门来&#xff0c;说可能是光猫用的时间太长了&#xff0c;换了一个新的联通光猫&#xff0c;问题解决。 wifi的名称是 CU_Y3ft 和 CU_Y3…

使用Docker一键部署Uptime Kuma,并将监控服务映射至公网访问

文章目录 **主要功能**一、前期准备本教程环境为&#xff1a;Centos7&#xff0c;可以跑Docker的系统都可以使用本教程安装。本教程使用Docker部署服务&#xff0c;如何安装Docker详见&#xff1a; 二、Docker部署Uptime Kuma三、实现公网查看网站监控四、使用固定公网地址访问…

web3风险投资公司之Electric Capital

文章目录 什么是 Electric CapitalElectric团队 Electric Capital 开发者报告参考 什么是 Electric Capital 官网&#xff1a;https://www.electriccapital.com/ 官方github&#xff1a;https://github.com/electric-capital Electric Capital 是一家投资于加密货币、区块链企…

[kubernetes]控制平面ETCD

什么是ETCD CoreOS基于Raft开发的分布式key-value存储&#xff0c;可用于服务发现、共享配置以及一致性保障&#xff08;如数据库选主、分布式锁等&#xff09;etcd像是专门为集群环境的服务发现和注册而设计&#xff0c;它提供了数据TTL失效、数据改变监视、多值、目录监听、…

面试官95%会问的接口测试知识!

接口测试最近几年被炒的火热了&#xff0c;越来越多的测试同行意识到接口测试的重要性。接口测试为什么会如此重要呢&#xff1f; 主要是平常的功能点点点&#xff0c;大家水平都一样&#xff0c;是个人都能点&#xff0c;面试时候如果问你平常在公司怎么测试的&#xff0c;你除…