尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

动态规划01背包问题

动态规划01背包问题
📅 发布时间:2026/6/19 16:02:06

动态规划:01背包问题

情景

现在有一个容量有限的背包(比如能装10公斤的东西),现在有价值不同,重量也不同的几件物品,我们要怎样装才能让这个背包尽可能的装的价值最高

这就是为什么这个问题叫01背包问题,每个物品只有两种状态,放入(1)和不放入(0)

问题

有一个背包,最大承重W=10。有4件物品:

  • 物品1:重量2,价值3
  • 物品2:重量3,价值4
  • 物品3:重量4,价值5
  • 物品4:重量5,价值6

问题:选择哪些物品放入背包,使总价值最大且总重量≤10?

普通解法
  1. 暴力计算

我们如果想把每个组合都试一遍,总能试出答案

#include<iostream>#include<vector>#include<algorithm>usingnamespacestd;intbruteForce01(vector<int>&values,vector<int>&weights,intcapacity){intn=values.size();intmaxVal=0;for(intmask=0;mask<(1<<n);mask++){intcurWeight=0,curValue=0;for(inti=0;i<n;i++){if(mask&(1<<i)){curWeight+=weights[i];curValue+=values[i];}}if(curWeight<=capacity){maxVal=max(maxVal,curValue);}}returnmaxVal;}intmain(){vector<int>values={3,4,5,6};vector<int>weights={2,3,4,5};intcapacity=10;cout<<"暴力解法结果: "<<bruteForce01(values,weights,capacity)<<endl;return0;}

确实算出了结果,但这个方法非常非常的麻烦,n = 4的情况下用了16种方法才试出答案,时间复杂度时O(n^2)

  1. 递归
#include<iostream>#include<vector>#include<algorithm>usingnamespacestd;intknapsackRecursive(inti,intremaining,vector<int>&values,vector<int>&weights){if(i==values.size())return0;intnotTake=knapsackRecursive(i+1,remaining,values,weights);inttake=0;if(remaining>=weights[i]){take=knapsackRecursive(i+1,remaining-weights[i],values,weights)+values[i];}returnmax(notTake,take);}intmain(){vector<int>values={3,4,5,6};vector<int>weights={2,3,4,5};intcapacity=10;cout<<"递归解法结果: "<<knapsackRecursive(0,capacity,values,weights)<<endl;return0;}

递归解法将这个二问题拆成小问题来解决,将选取这个物品和不选这个物品作比较,取最大值

这个解法看似没有暴力计算这么麻烦,但是在计算的过程中会有重叠子问题,重复的计算还是会带来效率的低下,那么为了避免重叠子问题,我们要使用动态规划

动态规划

二维数组

#include<iostream>#include<vector>#include<algorithm>usingnamespacestd;intknapsackDP(vector<int>&values,vector<int>&weights,intcapacity){intn=values.size();vector<vector<int>>dp(n+1,vector<int>(capacity+1,0));for(inti=1;i<=n;i++){intweight=weights[i-1];intvalue=values[i-1];for(intw=0;w<=capacity;w++){if(w<weight){dp[i][w]=dp[i-1][w];}else{dp[i][w]=max(dp[i-1][w],dp[i-1][w-weight]+value);}}}returndp[n][capacity];}intmain(){vector<int>values={3,4,5,6};vector<int>weights={2,3,4,5};intcapacity=10;cout<<knapsackDP(values,weights,capacity)<<endl;return0;}

我们创建了一个二维的数组,行代表考虑前i个物品,列代表背包当前的容量,两者合起来就是在考虑前i个物品时,背包容量为w时的最大值

现在将它初始化

现在对前k个物品进行外层遍历,在对背包的容量进行内层遍历,对于每个dp[i][w]我们都有两种情况,装的下和装不下,装不下那只能不选了,重在在于这个装的下,在这个时候,我们会有两种选择,装和不装,这时候就要比较不装的时候,和腾出该空间后剩下的价值比较

所以同样是比较,动态规划只需要计算一遍即可,比递归要快的多

一维数组

#include<iostream>#include<vector>#include<algorithm>usingnamespacestd;intknapsack01_1D(vector<int>&values,vector<int>&weights,intcapacity){intn=values.size();vector<int>dp(capacity+1,0);for(inti=0;i<n;i++){for(intw=capacity;w>=weights[i];w--){dp[w]=max(dp[w],dp[w-weights[i]]+values[i]);}}returndp[capacity];}intmain(){vector<int>values={3,4,5,6};vector<int>weights={2,3,4,5};intcapacity=10;cout<<knapsack01_1D(values,weights,capacity)<<endl;return0;}

dp[w]代表背包容量为w时的最大价值,仍然是熟悉的两层遍历,唯一不同的一点就是内层遍历变成了逆序遍历

为什么会这样?

这个数组只有一维,有限的空间使得计算时会包含当前的物品如果我们使用正序遍历,在dp的计算中会出现重复的计算,会存在一个物品被用了两次

所以我们使用逆序,从大容量向小容量思考,在计算dp时保证不含当前物品

解法对比表

比较维度暴力搜索普通递归动态规划(2D)动态规划(1D)
时间复杂度O(2ⁿ)O(2ⁿ)O(n×capacity)O(n×capacity)
是否重复计算大量重复(检查所有组合)大量重复(相同状态多次计算)无重复无重复
计算方向无方向自顶向下自底向上自底向上
代码复杂度简单中等中等中等(需理解逆序)
适用数据规模n≤15n≤20大中规模大规模
核心优势简单直观思维自然标准模板易理解空间最优速度快

总结

学习01背包问题更能理解动态规划的本质,理解其中空间换时间的思想,这篇文章是我之前动态规划的进一步学习,也为学习后边其他背包问题做铺垫

相关新闻

  • 停止造Agent,开始造Skills吧!Claude Skills创造者:Agent聪明但不够专业,非技术人员也能造Skills
  • 游戏中的开发模式有哪些?一篇带你了解常用的设计模式!<二>
  • 2025年男孩起名机构推荐:权威起名榜单TOP5深度解析 - 十大品牌推荐

最新新闻

  • Xournal++终极字体配置指南:告别混乱,打造完美手写笔记
  • MC68HC908GR8中断与复位机制详解:从原理到实战避坑指南
  • AI专著撰写新利器!一键生成20万字专著,高效解决写作难题!
  • 深耕重庆十一载,戴文润滑油的品质之路 - 技术实力派
  • 淮南寿县考不上高中,可关注淮南这所公办技师学校 - 我叫小周
  • 昆明家电维修平台推荐:本地用户反馈较好的几家服务商深度实测对比——2026年6月最新发布 - 一步到家

日新闻

  • 信任的进化:技术实现详解——如何用JavaScript构建博弈论模拟器
  • Terrakube自定义工作流:如何集成OPA、Infracost等工具扩展IaC能力
  • grunt-concurrent快速入门:5分钟学会并行运行Grunt任务

周新闻

  • 3步解锁iOS设备:applera1n激活锁绕过完全指南
  • 39 2026 人工智能证书终极盘点,普通人选 AI 证书可以从这些方向入手
  • Redis 暴露公网有多危险?从端口检查到补救步骤

月新闻

  • 【总结】入门篇:50句话让你记住架构核心概念
  • WeChatMsg技术方案解析:实现Mac微信数据自主管理的完整解决方案
  • WeChatMsg:革新性微信数据备份方案,打造你的专属数字记忆库

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号