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

01背包问题 - 动态规划最优解法(Java实现)

01背包问题 - 动态规划最优解法(Java实现)

问题描述

01背包问题是经典的动态规划问题:

  • 有一个容量为 W 的背包
  • n 个物品,每个物品有重量 weights[i] 和价值 values[i]
  • 每个物品只能选择一次(要么选0个,要么选1个)
  • 目标:在不超过背包容量的前提下,使背包中物品总价值最大

最推荐的Java解决方案

public static int knapsack(int[] weights, int[] values, int capacity) {int n = weights.length;// dp[i][w]表示前i个物品放入容量为w的背包中能获得的最大价值int[][] dp = new int[n + 1][capacity + 1];// 填充dp表for (int i = 1; i <= n; i++) {for (int w = 1; w <= capacity; w++) {// 当前物品的重量和价值(注意索引转换)int weight = weights[i - 1];int value = values[i - 1];if (weight <= w) {// 当前物品重量不超过背包容量,可以选择// 取不选择和选择当前物品的最大值dp[i][w] = Math.max(dp[i - 1][w], dp[i - 1][w - weight] + value);} else {// 当前物品重量超过背包容量,不能选择dp[i][w] = dp[i - 1][w];}}}return dp[n][capacity];
}

关键变量详解

变量含义作用
dp[i][w]前i个物品放入容量为w的背包能获得的最大价值状态定义,存储子问题的最优解
n物品总数确定dp数组的行数
capacity背包容量确定dp数组的列数
weight当前考虑物品的重量判断是否能放入背包
value当前考虑物品的价值计算选择该物品后的总价值
i当前考虑到第i个物品循环控制变量,表示子问题规模
w当前考虑的背包容量循环控制变量,表示子问题的容量限制

完整可视化演示

使用测试用例:

  • 物品信息:[重量: [2,3,4,5], 价值: [1,4,5,7]]
  • 背包容量:8

初始化阶段

DP表初始状态(dp[i][w] = 0):w=0  w=1  w=2  w=3  w=4  w=5  w=6  w=7  w=8
i=0     0    0    0    0    0    0    0    0    0
i=1     0    0    0    0    0    0    0    0    0  
i=2     0    0    0    0    0    0    0    0    0
i=3     0    0    0    0    0    0    0    0    0
i=4     0    0    0    0    0    0    0    0    0

逐步填充过程

第1轮:考虑物品1 (重量=2, 价值=1)
当前物品:物品1 [重量=2, 价值=1]

填充 dp[1][1]

  • weight=2 > w=1分支1:不能选择
  • dp[1][1] = dp[0][1] = 0

填充 dp[1][2]

  • weight=2 <= w=2分支2:可以选择
  • 不选:dp[0][2] = 0
  • 选择:dp[0][2-2] + 1 = 0 + 1 = 1
  • dp[1][2] = Math.max(0, 1) = 1

填充 dp[1][3] 到 dp[1][8]

  • 都满足 weight=2 <= w,选择物品1更优
  • dp[1][3] = dp[1][4] = ... = dp[1][8] = 1
第1轮完成后:w=0  w=1  w=2  w=3  w=4  w=5  w=6  w=7  w=8
i=0     0    0    0    0    0    0    0    0    0
i=1     0    0    1    1    1    1    1    1    1  ← 新填充
i=2     0    0    0    0    0    0    0    0    0
i=3     0    0    0    0    0    0    0    0    0
i=4     0    0    0    0    0    0    0    0    0
第2轮:考虑物品2 (重量=3, 价值=4)
当前物品:物品2 [重量=3, 价值=4]

关键计算 dp[2][5]

  • weight=3 <= w=5分支2:可以选择
  • 不选:dp[1][5] = 1
  • 选择:dp[1][5-3] + 4 = dp[1][2] + 4 = 1 + 4 = 5
  • dp[2][5] = Math.max(1, 5) = 5关键比较分支
第2轮完成后:w=0  w=1  w=2  w=3  w=4  w=5  w=6  w=7  w=8
i=0     0    0    0    0    0    0    0    0    0
i=1     0    0    1    1    1    1    1    1    1
i=2     0    0    1    4    4    5    5    5    5  ← 新填充
i=3     0    0    0    0    0    0    0    0    0
i=4     0    0    0    0    0    0    0    0    0
第3轮:考虑物品3 (重量=4, 价值=5)
当前物品:物品3 [重量=4, 价值=5]

关键计算 dp[3][7]

  • weight=4 <= w=7分支2:可以选择
  • 不选:dp[2][7] = 5
  • 选择:dp[2][7-4] + 5 = dp[2][3] + 5 = 4 + 5 = 9
  • dp[3][7] = Math.max(5, 9) = 9关键比较分支
第3轮完成后:w=0  w=1  w=2  w=3  w=4  w=5  w=6  w=7  w=8
i=0     0    0    0    0    0    0    0    0    0
i=1     0    0    1    1    1    1    1    1    1
i=2     0    0    1    4    4    5    5    5    5
i=3     0    0    1    4    5    6    9    9    9  ← 新填充
i=4     0    0    0    0    0    0    0    0    0
第4轮:考虑物品4 (重量=5, 价值=7)
当前物品:物品4 [重量=5, 价值=7]

关键计算 dp[4][8]

  • weight=5 <= w=8分支2:可以选择
  • 不选:dp[3][8] = 9
  • 选择:dp[3][8-5] + 7 = dp[3][3] + 7 = 4 + 7 = 11
  • dp[4][8] = Math.max(9, 11) = 11关键比较分支

填充 dp[4][4]

  • weight=5 > w=4分支1:不能选择
  • dp[4][4] = dp[3][4] = 5
最终DP表:w=0  w=1  w=2  w=3  w=4  w=5  w=6  w=7  w=8
i=0     0    0    0    0    0    0    0    0    0
i=1     0    0    1    1    1    1    1    1    1
i=2     0    0    1    4    4    5    5    5    5
i=3     0    0    1    4    5    6    9    9    9
i=4     0    0    1    4    5    7   10   11   11  ← 最终答案

代码分支覆盖分析

通过上述演示用例,我们完全覆盖了Java代码的所有分支:

分支1:weight > w(不能选择)

  • 触发位置:dp[1][1], dp[4][4] 等
  • 代码执行dp[i][w] = dp[i-1][w]
  • 说明:当前物品太重,无法放入背包

分支2:weight <= w(可以选择)

  • 触发位置:dp[1][2], dp[2][5], dp[3][7], dp[4][8] 等
  • 代码执行dp[i][w] = Math.max(dp[i-1][w], dp[i-1][w-weight] + value)

Math.max的比较分支

  • 不选更优:dp[2][3] = max(1, 4) → 选择4
  • 选择更优:dp[2][5] = max(1, 5) → 选择5
  • 关键比较:dp[4][8] = max(9, 11) → 选择11

算法复杂度

  • 时间复杂度:O(n × capacity),需要填充 n×capacity 个状态
  • 空间复杂度:O(n × capacity),需要存储 n×capacity 个状态

最终答案

通过动态规划,我们得到最优解是 11,对应的最优选择方案是:

  • 选择物品2(重量=3,价值=4)
  • 选择物品4(重量=5,价值=7)
  • 总重量:3+5=8 ≤ 8 ✓
  • 总价值:4+7=11

这个解法简洁易懂,逻辑清晰,是01背包问题的最推荐实现方式。


文章转载自:

http://zKsacypZ.npfrj.cn
http://utqj4zPS.npfrj.cn
http://4xwmkRsi.npfrj.cn
http://5YGwNbdA.npfrj.cn
http://ab4Q9CBd.npfrj.cn
http://X1Xo7pcc.npfrj.cn
http://n3wUOZz2.npfrj.cn
http://3ICQ9rYv.npfrj.cn
http://rPRpQMU7.npfrj.cn
http://UzQbRJe5.npfrj.cn
http://uFXdQvlr.npfrj.cn
http://rJ3fkcZh.npfrj.cn
http://7wkyAQgi.npfrj.cn
http://JvFUrB4R.npfrj.cn
http://kxgneDkb.npfrj.cn
http://1uGEcJt6.npfrj.cn
http://rWmHe16G.npfrj.cn
http://MAC0Pwxb.npfrj.cn
http://XXUcjfO9.npfrj.cn
http://zo8gjGo4.npfrj.cn
http://sp8XhA3r.npfrj.cn
http://YwWQbXbQ.npfrj.cn
http://yJFyYxby.npfrj.cn
http://NXfUX5SV.npfrj.cn
http://L8as3JRk.npfrj.cn
http://YTLEyiq3.npfrj.cn
http://AUUG9TqD.npfrj.cn
http://fTsxTMnm.npfrj.cn
http://0PLSlGVF.npfrj.cn
http://CTL1m36x.npfrj.cn
http://www.dtcms.com/a/379303.html

相关文章:

  • github 中的issues都有那些作用
  • 大健康时代下的平台电商:VTN平台以科研创新重构健康美丽消费生态
  • 【自记】SQL 中 GROUPING 和 GROUPING SETS 语句的案例说明
  • Codeforces Round 1048 (Div. 2)
  • CFD专栏丨ultraFluidX 动力舱热仿真
  • QTday1作业
  • Linux基本指令(7)
  • 车载数据采集(DAQ)解析
  • 计算机组成原理:定点加法、减法运算
  • Cursor 不香了?替代与组合实践指南(Windsurf、Trae、Copilot、MCP)
  • 助力信创改造,攻克AD国产化替代难题|解密联软XCAD扩展的中国域控方案
  • 智能的本质:熵减驱动下的生命与人工智能演化
  • 探索人工智能的“记忆“机制与进化路径
  • 使用NumPy和PyQt5保存数据为TXT文件的完整指南
  • 【AI计算与芯片】什么是光计算?
  • 爱校对正式入驻抖音店铺,为更多用户带来专业文字校对服务
  • 项目1——单片机程序审查,控制系统流程图和时序图
  • 完美解决:应用版本更新,增加字段导致 Redis 旧数据反序列化报错
  • 探索数据库世界:从基础类型到实际应用
  • ui指针遇到问题
  • 安卓13_ROM修改定制化-----禁用 Android 导航按键的几种操作
  • VMWare使用文件夹共享操作步骤
  • 【Nginx开荒攻略】Nginx入门:核心概念与架构设计
  • MQTT协议回顾
  • 端到端语音交互数据 精准赋能语音大模型进阶
  • 大模型在题目生成中的安全研究:攻击方法与防御机制
  • 可达性分析: 什么东西可以被当作根
  • Spring框架中的常见面试题
  • JavaScript 中 map 和 filter 方法的快速上手指南 (附综合案例)
  • C#写字符串到Modbus中