当前位置: 首页 > news >正文

动态规划 背包问题

动态规划 背包问题

问题描述:
有一个背包,总容量为12。有6件物品,每件物品的重量和价值不同,求在背包总容量12的前提下,装进物品的最大价值以及装进物品的编号

单个物品重量和价值:

在这里插入图片描述

为方便进行思考,我们将物品按照重量价值递增,重新排序

在这里插入图片描述


针对此问题,我们可以先列一张表格,标识当前背包容量为j时,前i个物品的最大价值。

在这里插入图片描述

例如X(3,3),代表当背包容量为3时,前3个物品可装入的最大价值。


第一行X(0,0)X(0,12),代表当背包容量为0到12时,前0个物品可装入的最大价值,前0个物品不存在没有价值,即价值恒为0,因此第一行都填入0。

同理第一列X(0,0)X(6,0),代表当背包容量为0时,第0个物品到第6个物品可装入的最大价值,因为背包容量为0,没有物品可以装下,所以第一列都填入0。

在这里插入图片描述


X(1,1) 代表当背包容量为1时,前1个物品的最大价值。由于W(1)=1,刚好可以装入,那么X(i,j)=X(1,1)=V(1)=4 ,因此填入4。并且不论之后背包容量如何扩展,前1个物品的最大价值恒为4。

在这里插入图片描述


当开始第三行,即X(2,j) 填写时,就需要判断背包容量够不够装下当前物品,如果能装下,那装下当前物品和不装当前物品哪个价值最大:

  1. 背包装不下

    当背包容量j小于当前第i个物品重量W(i) 时,即j<W(i) 判断为装不下,此时的最大价值X(i,j) 与前一个X(i-1,j) 的最大价值一样,即X(i,j)=X(i-1,j)

  2. 背包装得下

    当背包容量j大于等于当前第i个物品重量W(i) 时,判断要不要装进背包。

    2.1:装入当前物品时的最大价值Value1
    背包总容量j减去当前物品的重量W(i) 后,获取剩余总容量的上一物品最大价值X(i-1,j-W(i)) 与当前物品的价值V(i) 相加,即 Value1=X(i-1,j-W(i)) + V(i)

    2.2:不装当前物品时的最大价值Value2
    前一个物品i-1在此背包总容量j情景下的最大价值X(i-1,j),即 Value2=X(i-1,j)

Value1-Value2 大于0则取当前和值Value1,反之取上一物品此背包总容量情景下的最大价值Value2

此时不理解上述公式没关系,跟着下面的填数去慢慢理解


X(2,1) 填数,首先判断背包能否装下:

j=1W(2)=2j<W(2),因此当背包容量为1时,物品2装不下,此时最大价值取前一个物品i-1此背包总容量j情景下的最大价值X(i-1,j)=X(2-1,1)=X(1,1)=4,因此X(2,1)=4

在这里插入图片描述


X(2,2) 填数,首先判断背包能否装下:

j=2W(2)=2j=W(2),因此当背包容量为2时,物品2装得下

此时需要判断要不要装物品2:

装入当前物品时的最大价值:Value1 = X(i-1,j-W(i)) + V(i) = X(2-1,2-2) + 1 = X(1,0) + 1 = 0 + 1 = 1

不装当前物品时的最大价值:Value2 = X(i-1,j) = X(2-1,2) = X(1,2) = 4

Value1<Value2,因此取上一物品此背包总容量情景下的最大价值,即X(2,2) = X(1,2) = 4

在这里插入图片描述


X(2,3) 填数,首先判断背包能否装下:

j=3W(2)=2j>W(2),因此当背包容量为3时,物品2装得下

此时需要判断要不要装物品2:

装入当前物品时的最大价值:Value1 = X(i-1,j-W(i)) + V(i) = X(2-1,3-2) + 1 = X(1,1) + 1 = 4 + 1 = 5

不装当前物品时的最大价值:Value2 = X(i-1,j) = X(2-1,3) = X(1,3) = 4

Value1>Value2,因此取当前物品的价值加剩余总容量的最佳价值,即X(2,3) = 5

在这里插入图片描述


按照此规律,我们将表全部填充完毕:

在这里插入图片描述

取两个坐标进行验证:


例如1:X(4,3) 填数,首先判断背包能否装下:

j=3W(4)=3j=W(4),因此当背包容量为3时,物品4装得下

此时需要判断要不要装物品4:

装入当前物品时的最大价值:Value1 = X(i-1,j-W(i)) + V(i) = X(4-1,3-3) + 6 = X(3,0) + 6 = 0 + 6 = 6

不装当前物品时的最大价值:Value2 = X(i-1,j) = X(4-1,3) = X(3,3) = 7

Value1<Value2,因此取上一物品此背包总容量情景下的最大价值,即X(4,3) = X(3,3) = 7


例如2:X(4,4) 填数,首先判断背包能否装下:

j=4W(4)=3j>W(4),因此当背包容量为4时,物品4装得下

此时需要判断要不要装物品4:

装入当前物品时的最大价值:Value1 = X(i-1,j-W(i)) + V(i) = X(4-1,4-3) + 6 = X(3,1) + 6 = 4 + 6 = 10

不装当前物品时的最大价值:Value2 = X(i-1,j) = X(4-1,4) = X(3,4) = 7

Value1>Value2,因此取当前物品的价值加剩余总容量的最佳价值,即X(4,3) = 10


代码实现

int bag = 12; // 背包总容量
int number = 6; // 物品数量
int[] weight = {1, 2, 2, 3, 4, 6}; // 物品重量数组
int[] value = {4, 1, 3, 6, 8, 2}; // 物品价值数组
int[][] max = new int[number + 1][bag + 1]; // 最大价值数组int value1 = 0; // 过渡值:装入当前物品时的最大价值
int value2 = 0; // 过渡值:不装当前物品时的最大价值// 找出最大价值for (int i = 1; i <= number; i++) { // 行for (int j = 1; j <= bag; j++) { // 列// 判断背包能否装得下if (j < weight[i - 1]) { // 装不下max[i][j] = max[i - 1][j]; // 与前一个物品的最大价值相同} else { // 能装下// 前一个物品剩余重量的最大价值+当前物品的价值value1 = max[i - 1][j - weight[i - 1]] + value[i - 1];// 前一个物品当前重量的最大价值value2 = max[i - 1][j];// 取最大值max[i][j] = value1 > value2 ? value1 : value2;}}
}System.out.println(Arrays.deepToString(max)); // 打印最大价值数组
System.out.println("MaxValue = " + max[number][bag]); // 打印最大价值

结果输出:

[[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 
[0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4], 
[0, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5], 
[0, 4, 4, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8], 
[0, 4, 4, 7, 10, 10, 13, 13, 14, 14, 14, 14, 14], 
[0, 4, 4, 7, 10, 12, 13, 15, 18, 18, 21, 21, 22], 
[0, 4, 4, 7, 10, 12, 13, 15, 18, 18, 21, 21, 22]]
MaxValue = 22

在上述结果基础上,如果需要知道最大价值情况下,都装入了哪些商品,就需要进行回溯。

在这里插入图片描述

已知X[6][12] 为最大价值,首先判断它有没有装入背包,即X[6][12] = X[6-1][12] 是否生效,若相等,则未装入,继续以X[6-1][12] 作为最大价值进行判断。

X[5][12] 同理与X[5-1][12] 比较,发现不相等,通过公式22 = X[5-1][j-W(5)] + V[5] = X[4][12-4] + 8 = X[4][8] + 8 ,即X[4][8] = 22-8 = 14,反算后值也相等,则第5个物品装入了背包。

以此类推,公式为:

  1. 未装入背包
    X[i][j] = X[i-1][j],则当前物品未装入背包。

  2. 转入背包
    X[i-1][j-W(i)] = X[i][j] - V[i],则当前物品装入背包。


代码实现:


List list = new ArrayList<>(); // 装入物品编号// 回溯查找装入物品编号
findNo(number, bag);
Collections.sort(list); // 按照物品编号排序
System.out.println(list.toString());void findNo(int i, int j) {if (i > 0) {// 判断是否装入背包if (max[i][j] == max[i - 1][j]) {// 与上一物品最大价值相等,当前物品未装入findNo(i - 1, j);} else if (j - weight[i-1] >= 0 && (max[i - 1][j - weight[i-1]] == max[i][j] - value[i-1])) {  // 与上一物品最大价值不相等且反算成功,当前物品装入,继续递归list.add(i);findNo(i - 1, j - weight[i-1]);}}
}

结果输出:

[1, 2, 3, 4, 5]

相关文章:

动态规划 背包问题

动态规划 背包问题 问题描述&#xff1a; 有一个背包&#xff0c;总容量为12。有6件物品&#xff0c;每件物品的重量和价值不同&#xff0c;求在背包总容量12的前提下&#xff0c;装进物品的最大价值以及装进物品的编号 单个物品重量和价值&#xff1a; 为方便进行思考&#…...

C++ Primer Plus 学习笔记(四)—— 内存模型和名称空间

1 单独编译 C允许将组件函数放在独立的文件即头文件中&#xff0c;头文件中可以包含以下内容&#xff1a; 函数原型&#xff1b;使用#define或const定义的符号常量&#xff1b;结构声明&#xff1b;类声明&#xff1b;模板声明&#xff1b;内联函数。 注意&#xff0c;在包含…...

详解基于 Celestia、Eclipse 构建的首个Layer3 链 Nautilus Chain

以流支付为主要概念的Zebec生态&#xff0c;正在推动流支付这种新兴的支付方式向更远的方向发展&#xff0c;该生态最初以Zebec Protocol的形态发展&#xff0c;并从初期的Solana进一步拓展至BNB Chian以及Near上。与此同时&#xff0c;Zebec生态也在积极的寻求从协议形态向公链…...

列表与数组的转化

目录用np.array(a)将列表转换为数组列表转数组的特殊情况(一)列表转数组的特殊情况(二)针对子元素个数不一致的解决办法用a.tolist()函数将数组转化为列表在python的学习中&#xff0c;经常会用到数组与列表的相互转化&#xff0c;本文主要介绍下关于数组与列表转化的问题。用n…...

docker 运行花生壳实现内外网穿透

环境&#xff1a;centos 7 ,64位 1、创建一个指定的文件夹作为安装示例所用&#xff0c;该示例文件夹为“hsk-nwct”。“hsk-nwct”内创建“app”文件夹作为docker容器挂载出来的文件。 2、在“app”内下载花生壳linux安装包&#xff0c;下载花生壳应用&#xff1a;花生壳客户…...

操作系统——16.时间片轮转、优先级、多级反馈队列算法

这篇文章我们来看一下进程调度算法中的时间片轮转、优先级、多级反馈队列算法 目录 1.概述 2.时间片轮转调度算法&#xff08;RR&#xff0c;Round-Robin&#xff09; 3.优先级调度算法 4.多级反馈队列调度算法 5.分析对比 1.概述 首先&#xff0c;我们来看一下这篇文章…...

Python3.8.8-Django3.2-Redis-连接池-数据类型-字符串-list-hashmap-命令行操作

文章目录1.认识Redis1.1.优点1.2.缺点2.在Django中Redis的连接3.Redis的基础用法3.1.hashmap结构3.2.list结构4.命令行查看数据库5.作者答疑1.认识Redis Remote DIctionary Server(Redis) 是一个key-value 存储系统&#xff0c;是跨平台的非关系型数据库。是一个开源的使用 AN…...

Android kotlin 系列讲解(进阶篇)高级项目架构模式 - MVVM

<<返回总目录 1、MVVM是什么 MVVM是Model-View-ViewModel的缩写&#xff0c;是一种高级项目架构模式。 MVVM架构可以将程序结构主要分成三个部分&#xff1a; Model&#xff1a;数据模型部分&#xff0c;包括从服务端获取的json数据或者从本地获取的数据等等View&…...

8. 查找

1 题目描述 查找成绩10开启时间2021年09月24日 星期五 18:00折扣0.8折扣时间2021年11月15日 星期一 00:00允许迟交否关闭时间2021年11月23日 星期二 00:00 输入 n(n ≤ 10^6)个不超过 10^9的单调不减的&#xff08;就是后面的数字不小于前面的数字&#xff09;非负整数 &#…...

二分查找算法

感谢“五点七边”工作室的算法讲解&#xff0c;详细内容可以参考视频讲解 二分查找为什么总是写错&#xff1f;_哔哩哔哩_bilibili 此处仅是个人学习总结 以target等于5为例&#xff0c;输入: 1 2 3 5 5 5 8 9 1. 找到第一个 > target 的元素 判断条件 < target&am…...

Git(3)之远程服务器

Git基础之远程服务器 Author&#xff1a;onceday date&#xff1a;2023年3月5日 满满长路有人对你微笑过嘛… windows安装可参考文章&#xff1a;git简易配置_onceday_CSDN博客 參考文档&#xff1a; 《progit2.pdf》&#xff0c;Progit2 Github。《git-book.pdf》 文章目…...

Javalin解构

Javalin Javalin是一个轻量级http框架&#xff0c;我们可以很容易的了解请求的处理过程及其设计&#xff0c;具有较高的学习意义。 从demo说起 public static void main(String[] args) {Javalin app Javalin.create(config -> {System.out.println("用户配置"…...

yolov5算法,训练模型,模型检测

嘟嘟嘟嘟&#xff01;工作需要&#xff0c;所以学习了下yolov5算法。是干什么的呢&#xff1f; 通俗来说&#xff0c;可以将它看做是一个小孩儿&#xff0c;通过成年人&#xff08;开发人员&#xff09;提供的大量图片的学习&#xff0c;让自己知道我看到的哪些场景需要提醒给成…...

linux系统防火墙开放端口

linux系统防火墙开放端口 在外部访问CentOS中部署应用时&#xff0c;需要通过防火墙管理软件,开端口,或者直接关闭防火墙进行解决(不建议) 加粗样式 常用命令&#xff1a; systemctl start firewalld #启动 systemctl stop firewalld #停止 systemctl status firewalld #查看…...

CSAPP第九章 虚拟内存

理解虚拟内存的原因 本章前部分描述虚拟内存是如何工作的&#xff0c;后一部分描述应用程序如何使用和管理虚拟内存 物理和虚拟寻址 虚拟内存作为缓存的工具 页表 页命中 缺页 虚拟内存作为内存管理的工具 简化链接&#xff0c;简化加载&#xff0c;简化共享&#xff0c;简化…...

numpy数组与矩阵运算(二)

文章目录矩阵生成与常用操作矩阵生成矩阵转置查看矩阵特性矩阵乘法计算相关系数矩阵计算方差、协方差、标准差计算特征值与特征向量计算逆矩阵求解线性方程组奇异值分解函数向量化矩阵生成与常用操作 矩阵生成 扩展库numpy中提供的matrix()函数可以用来把列表、元组、range对…...

Dubbo 中 Zookeeper 注册中心原理分析

Dubbo 中 Zookeeper 注册中心原理分析 文章目录Dubbo 中 Zookeeper 注册中心原理分析一、ZooKeeper注册中心1.1 ZooKeeper数据结构1.2 ZooKeeper的Watcher机制1.3 ZooKeeper会话机制1.4 使用ZooKeeper作为注册中心二、源码分析2.1 AbstractRegistry2.2 FailbackRegistry2.2.1 核…...

素数产生新的算法(由筛法减法改为增加法)--哥德巴赫猜想的第一次实际应用

素数产生新的算法&#xff08;由筛法减法改为增加法&#xff09;--哥德巴赫猜想的第一次实际应用 摘要&#xff1a;长期以来&#xff0c;人们认为哥德巴赫猜想没有什么实际应用的。 现在&#xff0c;我假设这个不是猜想&#xff0c;而是定理或公理&#xff0c;就产生了新的应用…...

递归-需要满足三个条件

一&#xff0c;概述 递归是一种应用非常广泛的算法&#xff08;或者编程技巧&#xff09;。很多数据结构和算法的编码实现都要用到递归&#xff0c;比如 DFS 深度优先搜索、前中后序二叉树遍历等。 去的过程叫“递”&#xff0c;回来的过程叫“归”。基本上所有的递归问题都可…...

【剑指Offer-Java】两个栈实现队列

题目 用两个栈实现一个队列。队列的声明如下&#xff0c;请实现它的两个函数 appendTail 和 deleteHead &#xff0c;分别完成在队列尾部插入整数和在队列头部删除整数的功能。(若队列中没有元素&#xff0c;deleteHead 操作返回 -1 ) 输入&#xff1a; [“CQueue”,“appendT…...

ElevenLabs语音合成效果翻倍的秘密(行业未公开的声学参数调优矩阵)

更多请点击&#xff1a; https://intelliparadigm.com 第一章&#xff1a;ElevenLabs英文语音合成效果翻倍的核心洞察 关键瓶颈在于语音上下文建模粒度 ElevenLabs 的高质量语音合成并非单纯依赖更大模型参数量&#xff0c;而是通过细粒度的语义-韵律联合编码实现自然度跃升。…...

RAG 系列(十七):Agentic RAG——让 Agent 主导检索过程

Pipeline RAG 的沉默失败 前面十几篇一直在优化一件事:怎么让检索结果更好。更好的分块、更精准的排序、更聪明的问法、CRAG 纠偏、Graph RAG 关系遍历…… 但有一件事始终没变:无论检索结果好不好,都会被传给 LLM 生成答案。 Pipeline RAG 的流程是线性的、固定的: 问…...

深度集成AI的VSCode扩展:从代码生成到调试的全流程实战指南

1. 项目概述&#xff1a;一个为VSCode注入AI灵魂的扩展如果你和我一样&#xff0c;每天有超过8小时的时间是在Visual Studio Code&#xff08;VSCode&#xff09;里度过的&#xff0c;那么你一定对提升编码效率有着近乎偏执的追求。从代码补全、语法高亮到调试、版本控制&#…...

Aurora框架解析:一体化高性能云原生开发平台的设计与实践

1. 项目概述与核心价值如果你在开源社区里混迹过一段时间&#xff0c;尤其是对现代化、高性能的Web开发框架感兴趣&#xff0c;那么“Aurora”这个名字你大概率不会陌生。它不是一个简单的库或者工具&#xff0c;而是一个由社区驱动的、旨在构建下一代企业级应用开发平台的雄心…...

终极显卡调校指南:如何用NVIDIA Profile Inspector释放游戏性能

终极显卡调校指南&#xff1a;如何用NVIDIA Profile Inspector释放游戏性能 【免费下载链接】nvidiaProfileInspector 项目地址: https://gitcode.com/gh_mirrors/nv/nvidiaProfileInspector NVIDIA Profile Inspector是一款专为NVIDIA显卡用户设计的免费优化工具&…...

从零构建专属大语言模型:Self-LLM开源项目全流程实践指南

1. 项目概述与核心价值最近在开源社区里&#xff0c;一个名为datawhalechina/self-llm的项目引起了我的注意。乍一看&#xff0c;这像是一个关于大语言模型&#xff08;LLM&#xff09;的仓库&#xff0c;但“self”这个前缀又让人浮想联翩。经过一段时间的深入研究和实践&…...

Cursor-Tap插件:一键AI代码重构与文档生成实战指南

1. 项目概述&#xff1a;一个为 Cursor 编辑器注入灵魂的插件如果你和我一样&#xff0c;日常重度依赖 Cursor 这款 AI 驱动的代码编辑器&#xff0c;那你一定体会过那种“就差一点”的微妙感受。Cursor 的 AI 能力确实强大&#xff0c;但它的交互方式有时会让人感觉像是在和一…...

手把手教你用SystemVerilog Interface搭建一个可复用的DMA寄存器验证环境

基于SystemVerilog Interface构建模块化DMA验证环境的工程实践 在数字IC验证领域&#xff0c;DMA&#xff08;直接内存访问&#xff09;控制器作为关键IP核&#xff0c;其寄存器验证环境的搭建效率直接影响项目进度。传统验证方法中信号连接冗长、时序控制分散的问题&#xff…...

毫米波ISAC技术:车联网中的感知与通信融合方案

1. 毫米波ISAC系统概述在智能交通系统快速发展的今天&#xff0c;毫米波集成感知与通信(ISAC)技术正成为解决车联网(V2X)需求的关键方案。这项技术的核心创新点在于&#xff0c;它巧妙地将雷达感知和无线通信两大功能整合到同一硬件平台上&#xff0c;通过共享60GHz毫米波频段资…...

2026年冰袋吸水粉厂家大揭秘:选择指南与行业趋势题

随着冷链物流行业的快速发展&#xff0c;冰袋吸水粉作为冷链运输中不可或缺的保冷材料&#xff0c;其市场需求持续增长。然而&#xff0c;市场上冰袋吸水粉的质量参差不齐&#xff0c;如何选择一家值得信赖的厂家成为许多采购商关注的重点。本文将从行业背景、技术特点及市场趋…...