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

动态规划算法之背包问题详细解读(附带Java代码解读)

动态规划中的背包问题(Knapsack Problem)是经典问题之一,通常用来解决选择一组物品放入背包使得背包的价值最大化的问题。根据问题条件的不同,背包问题有很多种变体,如0-1背包问题完全背包问题多重背包问题等。这里,我们详细介绍最经典的0-1背包问题,并提供代码的详细解读。

1. 0-1背包问题简介

在0-1背包问题中,有一个容量为 C 的背包和 n 件物品。每件物品有两个属性:重量 w[i]价值 v[i]。目标是选择若干件物品放入背包,使得总重量不超过 C,并且背包中物品的总价值最大化。

问题的约束:
  1. 每件物品要么选择(放入背包),要么不选择,因此称为 0-1 背包问题。
  2. 背包的总重量不能超过 C
  3. 要最大化背包中物品的总价值。

2. 动态规划的思路

动态规划适用于背包问题,因为它具有最优子结构重叠子问题的性质。解决这个问题的核心在于:针对每一个物品,都有两种选择——要么放进背包,要么不放进背包。

状态定义

定义 dp[i][j] 表示前 i 件物品放入容量为 j 的背包时所能获得的最大总价值。

状态转移方程

对于每件物品 i

  1. 如果不将第 i 件物品放入背包,则最大价值就是 dp[i-1][j],即前 i-1 件物品的最大价值。
  2. 如果将第 i 件物品放入背包,则最大价值为 dp[i-1][j-w[i]] + v[i],即前 i-1 件物品在剩余容量 j-w[i] 时的最大价值加上当前物品的价值 v[i]

综合起来,状态转移方程为:

dp[i][j]=max(dp[i−1][j],dp[i−1][j−w[i]]+v[i])

初始条件

当背包容量为0时,无论选哪件物品,最大价值都是0,即 dp[i][0] = 0

3. Java代码实现

public class Knapsack {public static void main(String[] args) {// 定义物品的重量和价值int[] weights = {2, 3, 4, 5}; // 每个物品的重量int[] values = {3, 4, 5, 6};  // 每个物品的价值int capacity = 8; // 背包容量int n = weights.length; // 物品数量// 计算并输出背包的最大价值System.out.println("Maximum value in Knapsack = " + knapsack(weights, values, n, capacity));}// 动态规划方法解决0-1背包问题public static int knapsack(int[] weights, int[] values, int n, int capacity) {// 定义DP数组:dp[i][j] 表示前 i 件物品在容量为 j 时的最大价值int[][] dp = new int[n + 1][capacity + 1];// 填充DP表for (int i = 1; i <= n; i++) {for (int j = 1; j <= capacity; j++) {if (weights[i - 1] <= j) { // 当前物品可以放入背包dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - weights[i - 1]] + values[i - 1]);} else { // 当前物品无法放入背包dp[i][j] = dp[i - 1][j];}}}// 返回最后一个格子的值,即最大价值return dp[n][capacity];}
}

4. 详细解释代码

4.1 输入和输出

main 方法中,定义了物品的重量数组 weights[]、价值数组 values[],以及背包的总容量 capacity 和物品数量 n。然后调用 knapsack() 方法来计算背包中可以获得的最大价值。

4.2 knapsack() 函数详解
public static int knapsack(int[] weights, int[] values, int n, int capacity) {// 定义DP数组:dp[i][j] 表示前 i 件物品在容量为 j 时的最大价值int[][] dp = new int[n + 1][capacity + 1];

首先,定义了二维数组 dp[][],其中 dp[i][j] 表示前 i 件物品在背包容量为 j 时能够获得的最大总价值。数组的大小为 [n+1][capacity+1],因为我们需要处理物品数量从0到n、容量从0到capacity的所有情况。

4.3 初始化和状态转移
for (int i = 1; i <= n; i++) {for (int j = 1; j <= capacity; j++) {if (weights[i - 1] <= j) {dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - weights[i - 1]] + values[i - 1]);} else {dp[i][j] = dp[i - 1][j];}}
}

接下来,用两个嵌套的 for 循环遍历物品和背包容量,进行状态转移:

  • 外层循环 i 遍历每一件物品。
  • 内层循环 j 遍历背包的每个可能容量。

对于每个物品 i

  • 如果该物品的重量 weights[i-1] 小于或等于当前容量 j,可以选择放入背包或不放入背包,选择价值最大的方案。这就是通过状态转移方程 dp[i][j] = Math.max(dp[i-1][j], dp[i-1][j-weights[i-1]] + values[i-1]) 计算出的。
  • 如果该物品的重量 weights[i-1] 超过当前容量 j,则无法将其放入背包,此时只能继承前 i-1 件物品的最大价值,即 dp[i][j] = dp[i-1][j]
4.4 返回最大价值
return dp[n][capacity];

循环结束后,dp[n][capacity] 就是前 n 件物品在背包容量为 capacity 时能够获得的最大价值,因此返回该值。

5. 复杂度分析

  • 时间复杂度O(n * capacity),因为我们需要填充一个大小为 n * capacity 的表。
  • 空间复杂度O(n * capacity),因为我们使用了二维数组 dp[][] 存储中间结果。

6. 空间优化

在上述实现中,我们用了二维数组 dp[][] 来存储所有状态。但实际上,在每一行 i 的状态转移时,只依赖于上一行 i-1 的值。因此,我们可以将二维数组压缩为一维数组,从而降低空间复杂度到 O(capacity)

public static int knapsackOptimized(int[] weights, int[] values, int n, int capacity) {int[] dp = new int[capacity + 1];for (int i = 1; i <= n; i++) {// 从大到小遍历容量,保证每个物品只被计算一次for (int j = capacity; j >= weights[i - 1]; j--) {dp[j] = Math.max(dp[j], dp[j - weights[i - 1]] + values[i - 1]);}}return dp[capacity];
}
关键点:
  • 在每次迭代中,从容量 capacity 开始递减遍历,确保每个物品只更新一次。这种写法防止了在同一轮次中更新状态值时物品被重复选择。

7. 总结

0-1背包问题通过动态规划求解,有明确的状态转移方程。使用二维DP表来记录每个物品在不同容量下的最大价值,最终得到最优解。通过压缩空间,可以进一步优化到一维DP表。

相关文章:

动态规划算法之背包问题详细解读(附带Java代码解读)

动态规划中的背包问题&#xff08;Knapsack Problem&#xff09;是经典问题之一&#xff0c;通常用来解决选择一组物品放入背包使得背包的价值最大化的问题。根据问题条件的不同&#xff0c;背包问题有很多种变体&#xff0c;如0-1背包问题、完全背包问题、多重背包问题等。这里…...

Vue3+TypeScript二次封装axios

安装如下 npm install axios 第一步&#xff1a;创建config配置文件&#xff0c;用于存放请求后端的ip地址&#xff0c;用于后期打包后便于修改ip地址。 注&#xff1a;typescript要求参数要有类型。&#xff08;ES6 定义对象 属性 类型 修改的是属性的值&#xff09; inte…...

华为 HCIP-Datacom H12-821 题库 (16)

有需要题库的可以加下方Q群 V群进行学习交流 1. OSPF 邻居关系建立出现故障&#xff0c;通过 display ospf error 命令来检查&#xff0c;输出结果如图所示&#xff0c;根据图中内容分析&#xff0c;邻居建立失败的原因可能是以下哪一项&#xff1f; A、Process ID 不一致 B、…...

【论文分享精炼版】 sNPU: Trusted Execution Environments on Integrated NPUs

今天在COMPASS分享了之前写的一个博客&#xff0c;做了进一步的提炼总结&#xff0c;大家可以看看原文~ 今天分享的论文《sNPU: Trusted Execution Environments on Integrated NPUs》来自2024年ISCA&#xff0c;共同一作为Erhu Feng以及Dahu Feng。并且&#xff0c; 这两位作…...

MyBatis 入门之动态 SQL

文章目录 一、什么是动态 SQL二、MyBatis 中的动态 SQL 标签三、动态 SQL 的使用示例四、总结 在 Java 开发中&#xff0c;MyBatis 是一个非常流行的持久层框架&#xff0c;它提供了强大的 SQL 映射功能和动态 SQL 支持。动态 SQL 可以根据不同的条件动态地生成 SQL 语句&#…...

软工大二学生待办事项:

该文章会常年更新!坚持! 2024.9.10 学习打包部署 记录睡眠 开始刷一个算法 巩固Git版本控制工具的使用 巩固利用Idea使用版本管理工具,SQl编写 抓紧时间了解公司营业执照 坚持到周末再打瓦!...

MongoDB延迟查询

在 MongoDB 中&#xff0c;查看副本集成员之间的副本延迟可以通过以下步骤进行&#xff1a; 使用 rs.status() 命令&#xff1a; 这个命令提供了副本集的详细状态信息&#xff0c;包括每个成员的延迟情况。在 MongoDB shell 中&#xff0c;你可以执行以下命令&#xff1a; rs.s…...

python如何获取html中的所有链接

在Python中&#xff0c;获取HTML页面中的所有链接通常可以通过使用第三方库如BeautifulSoup或lxml来完成。这里&#xff0c;我将提供一个使用BeautifulSoup库的示例&#xff0c;因为它简单易用且功能强大。 首先&#xff0c;你需要安装BeautifulSoup和requests库&#xff08;如…...

79-java static修饰的类能不能被继承

Java中的类可以被final关键字修饰&#xff0c;表示这个类不能被继承。如果一个类被final修饰&#xff0c;那么这个类不能被继承&#xff0c;也就是说&#xff0c;final类不能被继承。 另一方面&#xff0c;static关键字可以用来修饰内部类&#xff0c;这样的内部类是静态内部类…...

MacOS wine中文乱码问题

安装wine 1、brew update 执行失败&#xff0c;提示安装如下 2、git -C /usr/local/Homebrew/Library/Taps/homebrew/homebrew-cask fetch --unshallow 3、git -C /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core fetch --unshallow 3、brew update 4、brew in…...

基于Springboot的鲜花销售网站的设计与实现

项目描述 这是一款基于Springboot的鲜花销售网站的系统 模块描述 鲜花销售系统 1、用户 登录 在线注册 浏览商品 鲜花搜索 订购商品 查询商品详情 水果分类查看 水果加购物车 下单结算 填写收货地址 2、管理员 登录 用户管理 商品管理 订单管理 账户管理 截图...

安卓玩机工具-----适合安卓机型的“搞机工具箱” 功能齐全 玩机推荐

搞机工具箱最新版是一款相当出色的电脑端手机工具箱软件&#xff0c;搞机工具箱正式版功能强劲&#xff0c;可以帮助用户不需要root就能够直接对手机进行调节&#xff0c;方便对手机进行更加全面的掌控&#xff0c;搞机工具箱便捷好用&#xff0c;只需要根据文字提示及自己的需…...

数据分析-17-时间序列分析的平稳性检验

1 什么是时间序列 时间序列是一组按时间顺序排列的数据点的集合,通常以固定的时间间隔进行观测。这些数据点可以是按小时、天、月甚至年进行采样的。时间序列在许多领域中都有广泛应用,例如金融、经济学、气象学和工程等。 时间序列的分析可以帮助我们理解和预测未来的趋势和…...

Unity3D Android多渠道极速打包方案详解

在移动应用开发过程中&#xff0c;特别是在使用Unity3D进行Android游戏或应用开发时&#xff0c;多渠道打包是一个常见且重要的需求。不同的渠道&#xff08;如Google Play、华为应用市场、小米应用商店等&#xff09;可能需要不同的配置和包名&#xff0c;手动进行这些操作既耗…...

数据库中的主键和外键分别是什么意思?

让我们来聊聊数据库设计中非常重要的两个概念——主键&#xff08;Primary Key&#xff09;和外键&#xff08;Foreign Key&#xff09;。这两个概念对于保证数据的一致性和完整性至关重要。 主键&#xff08;Primary Key&#xff09; 主键是一个表中的一个或一组字段&#x…...

HTML5中`<ul>`标签深入全面解析

在HTML5的广阔天地里&#xff0c;<ul>标签作为无序列表的代言人&#xff0c;扮演着举足轻重的角色。它不仅能够整洁地罗列信息&#xff0c;还通过丰富的属性和样式选项&#xff0c;为网页设计师提供了无限的创意空间。本文将深入剖析<ul>标签的内核&#xff0c;详细…...

MongoDB日志级别

日志 查看当前的日志级别 根据你提供的 MongoDB 命令结果&#xff0c;命令 db.adminCommand({ getParameter: "logComponentVerbosity" }) 返回了 "ok" : 0&#xff0c;这意味着命令执行失败&#xff0c;没有成功获取到日志级别的配置信息。错误信息 &quo…...

Softmax回归--分类--有监督

输出和类别的维度一样。 一、当我们想将先线性层的输出直接视为概率&#xff0c;存在一些问题&#xff1a; 1.不能限制输出数字总和为1。 2.不能保证都是正数。 所以会使用softmax进行归一化。 二、交叉熵损失 交叉熵是一个衡量两个概率分布之间差异的很好的度量&#xff0…...

Jenkins生成html报告

下载插件 1.需要下载插件 html Publisher plugins 2.下载Groovy(设置css样式&#xff09;&#xff0c;默认没有css样式 在Job配置页面&#xff0c;增加构建步骤Execute system Groovy script&#xff0c;在Groovy Command中输入上面命令&#xff0c;即可&#xff1a; System.…...

牛客——查找字符串

B-你好&#xff0c;这里是牛客竞赛_牛客周赛 Round 59 (nowcoder.com) 返回值是子串或字符在 string 对象字符串中的位置 #include <bits/stdc.h> using namespace std; int T; string s; int main() { cin >> T; while(T --) { cin >>…...

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?

编辑&#xff1a;陈萍萍的公主一点人工一点智能 未来机器人的大脑&#xff1a;如何用神经网络模拟器实现更智能的决策&#xff1f;RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战&#xff0c;在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…...

反向工程与模型迁移:打造未来商品详情API的可持续创新体系

在电商行业蓬勃发展的当下&#xff0c;商品详情API作为连接电商平台与开发者、商家及用户的关键纽带&#xff0c;其重要性日益凸显。传统商品详情API主要聚焦于商品基本信息&#xff08;如名称、价格、库存等&#xff09;的获取与展示&#xff0c;已难以满足市场对个性化、智能…...

图表类系列各种样式PPT模版分享

图标图表系列PPT模版&#xff0c;柱状图PPT模版&#xff0c;线状图PPT模版&#xff0c;折线图PPT模版&#xff0c;饼状图PPT模版&#xff0c;雷达图PPT模版&#xff0c;树状图PPT模版 图表类系列各种样式PPT模版分享&#xff1a;图表系列PPT模板https://pan.quark.cn/s/20d40aa…...

【开发技术】.Net使用FFmpeg视频特定帧上绘制内容

目录 一、目的 二、解决方案 2.1 什么是FFmpeg 2.2 FFmpeg主要功能 2.3 使用Xabe.FFmpeg调用FFmpeg功能 2.4 使用 FFmpeg 的 drawbox 滤镜来绘制 ROI 三、总结 一、目的 当前市场上有很多目标检测智能识别的相关算法&#xff0c;当前调用一个医疗行业的AI识别算法后返回…...

AspectJ 在 Android 中的完整使用指南

一、环境配置&#xff08;Gradle 7.0 适配&#xff09; 1. 项目级 build.gradle // 注意&#xff1a;沪江插件已停更&#xff0c;推荐官方兼容方案 buildscript {dependencies {classpath org.aspectj:aspectjtools:1.9.9.1 // AspectJ 工具} } 2. 模块级 build.gradle plu…...

云原生玩法三问:构建自定义开发环境

云原生玩法三问&#xff1a;构建自定义开发环境 引言 临时运维一个古董项目&#xff0c;无文档&#xff0c;无环境&#xff0c;无交接人&#xff0c;俗称三无。 运行设备的环境老&#xff0c;本地环境版本高&#xff0c;ssh不过去。正好最近对 腾讯出品的云原生 cnb 感兴趣&…...

【分享】推荐一些办公小工具

1、PDF 在线转换 https://smallpdf.com/cn/pdf-tools 推荐理由&#xff1a;大部分的转换软件需要收费&#xff0c;要么功能不齐全&#xff0c;而开会员又用不了几次浪费钱&#xff0c;借用别人的又不安全。 这个网站它不需要登录或下载安装。而且提供的免费功能就能满足日常…...

快刀集(1): 一刀斩断视频片头广告

一刀流&#xff1a;用一个简单脚本&#xff0c;秒杀视频片头广告&#xff0c;还你清爽观影体验。 1. 引子 作为一个爱生活、爱学习、爱收藏高清资源的老码农&#xff0c;平时写代码之余看看电影、补补片&#xff0c;是再正常不过的事。 电影嘛&#xff0c;要沉浸&#xff0c;…...

uniapp 字符包含的相关方法

在uniapp中&#xff0c;如果你想检查一个字符串是否包含另一个子字符串&#xff0c;你可以使用JavaScript中的includes()方法或者indexOf()方法。这两种方法都可以达到目的&#xff0c;但它们在处理方式和返回值上有所不同。 使用includes()方法 includes()方法用于判断一个字…...

android RelativeLayout布局

<?xml version"1.0" encoding"utf-8"?> <RelativeLayout xmlns:android"http://schemas.android.com/apk/res/android"android:layout_width"match_parent"android:layout_height"match_parent"android:gravity&…...