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

【算法系列之动态规划III】背包问题

背包问题

  1. 01背包指的是物品只有1个,可以选也可以不选。
  2. 完全背包是物品有无数个,可以选几个也可以不选。

二维数组01背包

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

输入: 
weight: [1,3,4],value: [15,20,30],背包体积: 4
输出:35

解题思路

  1. dp数组,从下标[0-i]的物品里面任意取,放进容量为j的背包,价值总和最大是多少。
  2. 不放物品i,物品i由于体积问题放不进去,dp[i][j]=dp[i-1][j]
  3. 放物品i,dp[i][j]=dp[i-1][j-weight[i]]+value[i]

Java实现

public class BagProblem {public static void main(String[] args) {int[] weight = {1, 3, 4};int[] value = {15, 20, 30};int bagSize = 4;System.out.println(new BagProblem().testWeightBagProblem(weight, value, bagSize));}public int testWeightBagProblem(int[] weight, int[] value, int bagSize) {int size = weight.length;//0-size-1个物品放入到大小为bagSize的背包中int[][] dp = new int[size][bagSize + 1];//当bagSize=0时,dp[i][0]=0//当只有索引为0的物品可以选择,且放的下(j<=bagSize),dp[0][j]的值等于放入索引为0的价值for (int j = weight[0]; j <= bagSize; j++) {dp[0][j] = value[0];}for (int i = 1; i < size; i++) {for (int j = 1; j <= bagSize; j++) {if (j < weight[i]) {/*** 当前背包的容量都没有当前物品i大的时候,是不放物品i的* 那么前i-1个物品能放下的最大价值就是当前情况的最大价值*/dp[i][j] = dp[i - 1][j];} else {dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]);}}}for (int i = 0; i < size; i++) {for (int j = 0; j <= bagSize; j++) {System.out.print(dp[i][j] + "\t");}System.out.println("\n");}return dp[size - 1][bagSize];}
}

一维数组01背包

解题思路

  1. dp[j]表示:容量为j的背包,所背的物品价值可以最大为dp[j]。
  2. 递推公式:dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);
  3. 遍历详解:当i=0,初始化dp[j],只有j>weight[i]的时候,会被初始化。当i=1的时候,可以选择的商品有[0,1],dp[j]是在原有的dp数组上判断的,只有当可以存放下索引为1的商品,且dp[j - weight[i]] + value[i]>dp[j],该数值才会被更新。
  4. 选择逆序背包容量,主要是dp[j]和dp[j-weight[i]]的初始化顺序的问题。在二维数组中,比较的是dp[i-1][j-weight[i]],是第i-1层的dp[j-weight[i]]

Java实现

public class BagProblem_II {public static void main(String[] args) {int[] weight = {1, 3, 4};int[] value = {15, 20, 30};int bagWight = 4;System.out.println(new BagProblem_II().testWeightBagProblem(weight, value, bagWight));}private int testWeightBagProblem(int[] weight, int[] value, int bagWeight) {int wLen = weight.length;//定义dp数组:dp[j]表示背包容量为j时,能获得的最大价值int[] dp = new int[bagWeight + 1];//遍历顺序:先遍历物品,再遍历背包容量for (int i = 0; i < wLen; i++) {for (int j = bagWeight; j >= weight[i]; j--) {dp[j] = Math.max(dp[j], dp[j - weight[i]] + value[i]);System.out.println(dp[j] + "," + j + "," + i);}}//打印dp数组for (int j = 0; j <= bagWeight; j++) {System.out.print(dp[j] + " ");}System.out.println();return dp[bagWeight];}
}

416. 分割等和子集

力扣题目链接

给你一个 只包含正整数非空 数组 nums 。请你判断是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。

输入:nums = [1,5,11,5]
输出:true
解释:数组可以分割成 [1, 5, 5] 和 [11] 。

解题思路

  1. 集合里能否出现总和为 sum / 2 的子集
  2. dp[j]:最大值为j的子集
  3. 如果第i个元素没有放到集合中,值是dp[i-1][j];如果第i个元素放进集合中,值是dp[i-1][j-num[i]]+num[i]
dp[i][j]= dp[i−1][j],当i-1的数组已经满足了等于j的条件
dp[i][j]= true, 当nums[i] = j满足。
dp[i−1][j−nums[i]].当nums[i] < j。
dp[i][j]为true的三个条件,只需要满足一个即可。

Java实现

    public boolean canPartition(int[] nums) {if (nums == null || nums.length == 0) return false;int len = nums.length;int sum = 0;for (int i = 0; i < nums.length; i++) {sum += nums[i];}if (sum % 2 != 0) {return false;}int target = sum / 2;int[] dp = new int[target + 1];for (int i = 0; i < len; i++) {for (int j = target; j >= nums[i]; j--) {dp[j] = Math.max(dp[j], dp[j - nums[i]] + nums[i]);}}return dp[target] == target;}

1049.最后一块石头的重量II

力扣题目链接

有一堆石头,用整数数组 stones 表示。其中 stones[i] 表示第 i 块石头的重量。

每一回合,从中选出任意两块石头,然后将它们一起粉碎。假设石头的重量分别为 xy,且 x <= y。那么粉碎的可能结果如下:

  • 如果 x == y,那么两块石头都会被完全粉碎;
  • 如果 x != y,那么重量为 x 的石头将会完全粉碎,而重量为 y 的石头新重量为 y-x

最后,最多只会剩下一块 石头。返回此石头 最小的可能重量 。如果没有石头剩下,就返回 0

输入:stones = [2,7,4,1,8,1]
输出:1
解释:
组合 2 和 4,得到 2,所以数组转化为 [2,7,1,8,1],
组合 7 和 8,得到 1,所以数组转化为 [2,1,1,1],
组合 2 和 1,得到 1,所以数组转化为 [1,1,1],
组合 1 和 1,得到 0,所以数组转化为 [1],这就是最优值。

解题思路

  1. dp[target]里是容量为target的背包所能背的最大重量。分成两堆石头,一堆石头的总重量是dp[target],另一堆就是sum - dp[target]。相撞之后剩下的最小石头重量就是 (sum - dp[target]) - dp[target]。

Java实现

class Solution_LC1049 {public int lastStoneWeightII(int[] stones) {int sum = 0;for (int i : stones) {sum += i;}int target = sum >> 1;//初始化dp数组int[] dp = new int[target + 1];for (int i = 0; i < stones.length; i++) {//采用倒序for (int j = target; j >= stones[i]; j--) {//两种情况,要么放,要么不放dp[j] = Math.max(dp[j], dp[j - stones[i]] + stones[i]);}}return sum - 2 * dp[target];}
}

494.目标和

力扣题目链接

给你一个整数数组 nums 和一个整数 target

向数组中的每个整数前添加 '+''-' ,然后串联起所有整数,可以构造一个 表达式

  • 例如,nums = [2, 1] ,可以在 2 之前添加 '+' ,在 1 之前添加 '-' ,然后串联起来得到表达式 "+2-1"

返回可以通过上述方法构造的、运算结果等于 target 的不同 表达式 的数目。

输入:nums = [1,1,1,1,1], target = 3
输出:5
解释:一共有 5 种方法让最终目标和为 3 。
-1 + 1 + 1 + 1 + 1 = 3
+1 - 1 + 1 + 1 + 1 = 3
+1 + 1 - 1 + 1 + 1 = 3
+1 + 1 + 1 - 1 + 1 = 3
+1 + 1 + 1 + 1 - 1 = 3

解题思路

  1. 数组集合可以分为正数集合和负数集合,正+负=sum,正-负=target,题目可以转化为求sum=正数的子集合的个数。
  2. 纯01背包问题:装满背包最大的价值是多少;分割等和子集,能不能装满这个背包;最后一块石头的重量,给定背包,能装多少装多少;目标和:装满这个背包有多少方法?
  3. dp数组的含义:填满j(包括j)这么大容积的包,有dp[j]种方法。
  4. dp[j]=dp[j-nums[i]]的累加。比如nums[i]=2,dp[5]+=dp[5-nums[i]]。

Java实现

class Solution_LC494 {public int findTargetSumWays(int[] nums, int target) {int len = nums.length;int sum = 0;for (int i = 0; i < len; i++) {sum += nums[i];}if (target > sum || target < -sum) {return 0;}if ((target + sum) % 2 != 0) {return 0;}int goal = (target + sum) / 2;//填满j(包括j)这么大容积的包,有dp[j]种方法int[] dp = new int[goal + 1];dp[0] = 1;for (int i = 0; i < nums.length; i++) {for (int j = goal; j >= nums[i]; j--) {dp[j] += dp[j - nums[i]];}}return dp[goal];}
}

二维数组的实现

class Solution {public int findTargetSumWays(int[] nums, int target) {int sum = 0;for (int num : nums) {sum += num;}int diff = sum - target;if (diff < 0 || diff % 2 != 0) {return 0;}int n = nums.length, neg = diff / 2;int[][] dp = new int[n + 1][neg + 1];dp[0][0] = 1;for (int i = 1; i <= n; i++) {int num = nums[i - 1];for (int j = 0; j <= neg; j++) {dp[i][j] = dp[i - 1][j];if (j >= num) {dp[i][j] += dp[i - 1][j - num];}}}return dp[n][neg];}
}

474.一和零

力扣题目链接

给你一个二进制字符串数组 strs 和两个整数 mn

请你找出并返回 strs 的最大子集的长度,该子集中 最多m0n1

如果 x 的所有元素也是 y 的元素,集合 x 是集合 y子集

输入:strs = ["10", "0001", "111001", "1", "0"], m = 5, n = 3
输出:4
解释:最多有 5 个 0 和 3 个 1 的最大子集是 {"10","0001","1","0"} ,因此答案是 4 。
其他满足题意但较小的子集包括 {"0001","1"} 和 {"10","1","0"} 。{"111001"} 不满足题意,因为它含 4 个 1 ,大于 n 的值 3 。

解题思路

  1. dp[i][j]表示i个0和j个1时的最大子集

Java实现

class Solution {public int findMaxForm(String[] strs, int m, int n) {int[][] dp = new int[m + 1][n + 1];for (String str : strs) {int zeroNum = 0;int oneNum = 0;for (int i = 0; i < str.length(); i++) {if (str.charAt(i) == '0') {zeroNum++;} else {oneNum++;}}for (int i = m; i >= zeroNum; i--) {for (int j = n; j >= oneNum; j--) {dp[i][j] = Math.max(dp[i][j], dp[i - zeroNum][j - oneNum] + 1);}}}return dp[m][n];}
}

总结一下

纯 0 - 1 背包 是求 给定背包容量 装满背包 的最大价值是多少。
416. 分割等和子集 是求 给定背包容量,能不能装满这个背包。
1049. 最后一块石头的重量 II 是求 给定背包容量,尽可能装,最多能装多少
494. 目标和 是求 给定背包容量,装满背包有多少种方法。
本题是求 给定背包容量,装满背包最多有多少个物品。

在这里插入图片描述

相关文章:

【算法系列之动态规划III】背包问题

背包问题 01背包指的是物品只有1个&#xff0c;可以选也可以不选。完全背包是物品有无数个&#xff0c;可以选几个也可以不选。 二维数组01背包 有n件物品和一个最多能背重量为w 的背包。第i件物品的重量是weight[i]&#xff0c;得到的价值是value[i] 。每件物品只能用一次&…...

MONAI-LayerFactory设计与实现

LayerFactory 用于创建图层的工厂对象&#xff0c;这使用给定的工厂函数来实际产生类型或构建可调用程序。这些函数是通过名称来参考的&#xff0c;可以在任何时候添加。 用到的关键技术点&#xff1a; 装饰器(Decorators), 例如&#xff1a;property装饰器&#xff0c;创建…...

Thinkphp 6.0路由的定义

本节课我们来了解一下路由方面的知识&#xff0c;然后简单的使用一下路由的功能。 一&#xff0e;路由简介 1. 路由的作用就是让 URL 地址更加的规范和优雅&#xff0c;或者说更加简洁&#xff1b; 2. 设置路由对 URL 的检测、验证等一系列操作提供了极大的便利性&#xff1b; …...

Kafka系列之:深入理解Kafka集群调优

Kafka系列之:深入理解Kafka集群调优 一、Kafka硬件配置选择二、Kafka内存选择三、CPU选择四、网络选择五、生产者调优六、broker调优七、消费者调优八、Kafka总体调优一、Kafka硬件配置选择 服务器台数选择: 2 * (生产者峰值生产速率 * 副本数 / 100) + 1磁盘选择: Kafka…...

creator-泄漏检测之资源篇

title: creator-泄漏检测之资源篇 categories: Cocos2dx tags: [creator, 优化, 泄漏, 内存] date: 2023-03-29 14:48:48 comments: false mathjax: true toc: true creator-泄漏检测之资源篇 前篇 资源释放 - https://docs.cocos.com/creator/manual/zh/asset/release-manager…...

【DevOps】Jenkins 运行任务时遇到 FATAL:Unable to produce a script file 报错(已解决)

文章目录一、问题描述二、定位原因三、解决方案四、其他方案五、总结关键词&#xff1a; Jenkins、Unable to produce a script file、UnmappableCharacterException、IOException: Failed to create a temp file on一、问题描述 由于使用的 Jenkins 存在安全漏洞&#xff08;…...

Web前端

WEB前端 HTMLCSSJavaScriptjQuery(js框架)Bootstrap(CSS框架)AJAXJSON 文章目录 WEB前端WEB前端三大核心技术Web开发工具文本编辑器集成开发环境(IDE)浏览器选择HTML什么是 HTML?HTML版本变迁HTML-HelloWorldHTML 文档 = 网页HTML 标签属性(Attribute)HTML 常用标签...

资源操作:Resources

文章目录1. Spring Resources概述1.2 Resource 接口1.3 Resource的实现类1.3.1 UrlResource访问网络资源1.3.2 ClassPathResource访问类路径下资源1.3.3 FileSystemResource访问文件系统资源1.3.4 ServletContextResource1.3.5、InputStreamResource1.3.6、ByteArrayResource1.…...

GDB调试的学习

很早就想在好好学一学gdb了&#xff0c;正好最近学算法&#xff08;以前一直以为干硬件不需要什么特别厉害的算法&#xff0c;结果现在卷起来了。大厂面试题也有复杂一些的算法了&#xff09; 下面的这些命令是别的博主总结的 GDB 调试过程_gdb调试过程_麷飞花的博客-CSDN博客…...

熵值法综合评价分析流程

熵值法综合评价分析流程 一、案例背景 当前有一份数据&#xff0c;是各品牌车各个维度的得分情况&#xff0c;现在想要使用熵值法进行综合评价&#xff0c;得到各品牌车的综合得分&#xff0c;从而进行车型优劣对比&#xff0c;为消费者提供购车依据。 数据如下&#xff08;数…...

使用Python Pandas库操作Excel表格的技巧

在数据分析和处理中&#xff0c;我们经常需要对Excel表格进行操作。Python Pandas库提供了丰富的API来读取、写入、修改Excel表格。本文将介绍如何使用Python Pandas库操作Excel表格&#xff0c;包括向Excel表格添加新行、创建Excel表格等。 1.向Excel表格添加新行 下面是一个…...

LeetCode练习七:动态规划上:线性动态规划

文章目录一、 动态规划基础知识1.1 动态规划简介1.2 动态规划的特征1.2.1 最优子结构性质1.2.2 重叠子问题性质1.2.3 无后效性1.3 动态规划的基本思路1.4 动态规划基础应用1.4.1 斐波那契数1.4.2 爬楼梯1.4.3 不同路径1.5 个人总结二、记忆化搜索2.1 记忆化搜索简介2.2 记忆化搜…...

基于正点原子F407开发版和SPI接口屏移植touchgfx完整教程(一)

一、相关软件包安装 1、打开cubemx包管理器 2、安装F4软件包 3、安装touchgfx软件包 二、工程配置 1、新建工程 2、sys配置 3、rcc配置 4、crc配置 5、添加touchgfx软件包 6、配置touchgfx软件包 将width和height改为自己屏幕尺寸 7、生成工程 三、代码修改 1、将屏幕相关驱…...

Linux--进程间通信

前言 上一篇相关Linux文章已经时隔2月&#xff0c;Linux的学习也相对于来说是更加苦涩&#xff1b;无妨&#xff0c;漫漫其修远兮,吾将上下而求索。 下面该片文章主要是对进程间通信进行介绍&#xff0c;还对管道&#xff0c;消息队列&#xff0c;共享内存&#xff0c;信号量都…...

hadoop伪分布式集群搭建

基于hadoop 3.1.4 一、准备好需要的文件 1、hadoop-3.1.4编译完成的包 链接: https://pan.baidu.com/s/1tKLDTRcwSnAptjhKZiwAKg 提取码: ekvc 2、需要jdk环境 链接: https://pan.baidu.com/s/18JtAWbVcamd2J_oIeSVzKw 提取码: bmny 3、vmware安装包 链接: https://pan.baidu…...

Qt 中的信息输出机制:QDebug、QInfo、QWarning、QCritical 的简单介绍和用法

Qt 中的信息输出机制介绍QDebug在 Qt 中使用 qDebug输出不同类型的信息浮点数&#xff1a;使用 %!f(MISSING) 格式化符号输出浮点数布尔值&#xff1a;使用 %! (MISSING)和 %! (MISSING)格式化符号输出布尔值对象&#xff1a;使用 qPrintable() 函数输出对象的信息qInfoqWarnin…...

C++读写excel文件的的第三方库

一、比较流行的库 1. OpenXLSX 用于读取、写入、创建和修改 Microsoft Excel (.xlsx) 文件的 C 库。 2. xlnt xlnt 是一个现代 C 库&#xff0c;用于操作内存中的电子表格以及从 XLSX 文件读取/写入它们&#xff0c;如ECMA 376 第 4 版中所述。xlnt 1.0 版的首次公开发布是在 …...

【关于Linux中----多线程(一)】

文章目录认识线程创建线程线程优点和缺点创建一批线程终止线程线程的等待问题认识线程 在一个程序里的一个执行路线就叫做线程&#xff08;thread&#xff09;。更准确的定义是&#xff1a;线程是“一个进程内部的控制序列”一切进程至少都有一个执行线程线程在进程内部运行&a…...

2023年全国最新安全员精选真题及答案34

百分百题库提供安全员考试试题、建筑安全员考试预测题、建筑安全员ABC考试真题、安全员证考试题库等&#xff0c;提供在线做题刷题&#xff0c;在线模拟考试&#xff0c;助你考试轻松过关。 11.&#xff08;单选题&#xff09;物料提升机附墙架设置要符合设计要求&#xff0c;但…...

数据出境是什么意思?我国数据出境合规要求是什么?

随着经济全球化深入以及云计算等技术的发展&#xff0c;数据在全球范围跨境流动。数据跨境在促进经济增长、加速创新的同时&#xff0c;对数据主权、数据权属、个人信息保护等一系列问题逐渐浮出水面。今天我们就先来了解一下数据出境是什么意思&#xff1f;我国数据出境合规要…...

配置MyBatis-Plus打印执行的 SQL 语句到控制台或日志文件中

配置MyBatis-Plus打印 1. 使用 log4j 或 logback 配置 MyBatis-Plus 支持多种日志框架&#xff0c;如 SLF4J, Commons Logging, Log4J, Log4J2 和 JDK logging。这里以 Logback 为例说明如何配置。 在你的 logback.xml 文件中添加如下配置&#xff1a; <configuration>&l…...

融智学三大基本定律——信息世界的根本法则体系:为跨模态知识处理、人机协同等前沿领域提供原理支撑

融智学三大基本定律——信息世界的根本法则体系摘要&#xff1a;融智学三大基本定律构成信息处理的核心理论体系。第一定律&#xff08;实部序位关系唯一守恒&#xff09;确立本质信息的稳定性&#xff1b;第二定律&#xff08;实部序位同义并列对应转换&#xff09;实现多元表…...

RAG系统的需求分析

这个是一个基于私有知识库的智能对话平台&#xff0c;允许用户上传文档构建专属知识库&#xff0c;并通过自然语言交互的方式查询和获取知识。它结合了大语言模型和向量检索技术&#xff0c;让用户通过对话的形式与自己的知识库进行高效交互应用场景个人用户场景:学习助手&…...

Ollama在Apple Silicon上预览,性能大提升

2026年3月30日&#xff0c;Ollama开启在Apple silicon上的预览&#xff0c;由苹果MLX框架支持&#xff0c;解锁新性能&#xff0c;加速繁重工作&#xff0c;还在多方面有显著改进。MLX驱动&#xff0c;性能飞升基于Apple silicon的Ollama构建在MLX框架上&#xff0c;利用统一内…...

如何3步掌握Home Assistant SSH Web终端:从零到精通的管理指南 ✨

如何3步掌握Home Assistant SSH Web终端&#xff1a;从零到精通的管理指南 ✨ 【免费下载链接】app-ssh Advanced SSH & Web Terminal - Home Assistant Community Apps 项目地址: https://gitcode.com/gh_mirrors/ad/app-ssh 在智能家居系统的日常维护中&#xff0…...

Conda环境回滚实战:当安装新包搞崩base环境时如何一键恢复

Conda环境回滚实战&#xff1a;当安装新包搞崩base环境时如何一键恢复 在Python开发中&#xff0c;conda作为包管理和环境管理的利器&#xff0c;几乎成为数据科学家的标配工具。但越是频繁使用conda&#xff0c;越容易遇到一个令人头疼的问题——在base环境中安装新包后&#…...

pg_textsearch:革新Postgres文本搜索的现代工具

【导语&#xff1a;GitHub上的pg_textsearch是一款适用于Postgres的现代排名文本搜索工具&#xff0c;具备简单语法、可配置参数等特性&#xff0c;目前已达v1.0.0版本可用于生产环境&#xff0c;对Postgres文本搜索领域带来新变革。】pg_textsearch&#xff1a;Postgres文本搜…...

2025年9月中国电子学会青少年软件编程(图形化)等级考试试卷(一级)答案 + 解析

25年3月一级真题在线测评&#xff1a;http://jw.52coding.site/s/mwIJDR 青少年软件编程&#xff08;图形化&#xff09;等级考试试卷&#xff08;一级&#xff09; 一、单选题(共25题&#xff0c;共50分) 1.当前舞台背景为最后一个背景“背景3”&#xff0c;使用“下一个背景”…...

高效双电源自动切换电路的设计与实现

1. 双电源自动切换电路的应用场景 双电源自动切换电路在现代电子设备中扮演着关键角色&#xff0c;它能确保设备在不同供电来源之间无缝切换&#xff0c;避免断电导致的系统崩溃。这种电路设计特别适合以下场景&#xff1a; 便携式设备&#xff1a;比如蓝牙音箱、移动电源等&am…...

万象视界灵坛代码实例:使用Gradio快速搭建像素风Web UI,零前端开发经验可用

万象视界灵坛代码实例&#xff1a;使用Gradio快速搭建像素风Web UI&#xff0c;零前端开发经验可用 1. 项目概述 万象视界灵坛是一款基于OpenAI CLIP模型的多模态智能感知平台&#xff0c;它将复杂的语义对齐功能包装在充满游戏感的像素风界面中。这个项目最大的特点是完全不…...