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

代码随想录算法训练营第三十九天| 01背包问题 二维、一维、416. 分割等和子集

46. 携带研究材料(二维)

思路:dp[i][j] 中i,j分别表示表示物品和背包容量。dp[i][j] 表示从下标为[0-i]的物品里任意取,放进容量为j的背包,价值总和最大是多少。在放物品时,有以下情况:

  • 不放物品i:背包容量为j,里面不放物品i的最大价值是dp[i - 1][j]。

  • 放物品i:背包空出物品i的容量后,背包容量为j - weight[i],dp[i - 1][j - weight[i]] 为背包容量为j - weight[i]且不放物品i的最大价值,那么dp[i - 1][j - weight[i]] + value[i] (物品i的价值),就是背包放物品i得到的最大价值。

递归公式:dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]);

在二维中遍历顺序正反都可以。

我的代码:

#include <bits/stdc++.h> using namespace std; int main() { int n,bagweight; cin>>n>>bagweight; vector<int> weight(n,0); vector<int> value(n,0); for(int i=0;i<n;i++) { cin>>weight[i]; } for(int i=0;i<n;i++) { cin>>value[i]; } vector<vector<int>> dp(n,vector<int>(bagweight+1,0)); for(int i=0;i<n;i++) { dp[i][0]=0; } for(int i=weight[0];i<=bagweight;i++) { dp[0][i]=value[0]; } for(int i=1;i<n;i++) { for(int j=1;j<=bagweight;j++) { if(j<weight[i]) dp[i][j]=dp[i-1][j]; else { dp[i][j]=max(dp[i-1][j],dp[i-1][j-weight[i]]+value[i]); } } } cout<<dp[n-1][bagweight]<<endl; return 0; } #include <bits/stdc++.h> using namespace std;

46. 携带研究材料(一维)

思路:在二维的时候,我们可以发现:如果把dp[i - 1]那一层拷贝到dp[i]上,表达式完全可以是:dp[i][j] = max(dp[i][j], dp[i][j - weight[i]] + value[i]);与其把dp[i - 1]这一层拷贝到dp[i]上,不如只用一个一维数组了,只用dp[j]。在一维dp数组中,dp[j]表示:容量为j的背包,所背的物品价值可以最大为dp[j]。一维中必须先遍历物品再遍历背包,并且要倒序遍历背包,这样才不会重复选择。

我的代码:

#include <bits/stdc++.h> using namespace std; int main() { int n,bagweight; cin>>n>>bagweight; vector<int> weight(n,0); vector<int> value(n,0); for(int i=0;i<n;i++) { cin>>weight[i]; } for(int i=0;i<n;i++) { cin>>value[i]; } vector<int> dp(bagweight+1,0); for(int i=0;i<n;++i) { for(int j=bagweight;j>=weight[i];j--) { dp[j]=max(dp[j],dp[j-weight[i]]+value[i]); } } cout<<dp[bagweight]<<endl; return 0; }

416. 分割等和子集

思路:首先,本题要求集合里能否出现总和为 sum / 2 的子集。既有一个只能装重量为 sum / 2的背包,商品为数字,这些数字能不能把这个背包装满。一个数字只有一个维度,即重量等于价值。当数字可以装满承载重量为 sum / 2 的背包的背包时,这个背包的价值也是 sum / 2。那么这道题就是装满了载重量为 sum / 2 的背包,如果最大价值是 sum / 2,说明正好被商品装满了。因为商品是数字,重量和对应的价值是相同的。dp[j]的数值一定是小于等于j的。当 dp[target] == target 的时候,背包就装满了。

我的代码:

class Solution { public: bool canPartition(vector<int>& nums) { int sum=0; for(int i=0;i<nums.size();i++) { sum+=nums[i]; } if(sum%2==1) return false; int target=sum/2; vector<int> dp(10001,0); for(int i=0;i<nums.size();++i) { for(int j=target;j>=nums[i];--j) { dp[j] = max(dp[j], dp[j - nums[i]] + nums[i]); } } if (dp[target] == target) return true; return false; } };

今日总结

今天的背包入门对于我之前完全没接触过还是有一些理解难度的,还是要自己去举例,自己去想一想怎么办,不能马马虎虎过去,加油!

http://www.jsqmd.com/news/455630/

相关文章:

  • 华为ADS 3.0实测:多模态融合如何解决雨雾天自动驾驶难题(附夜间测试视频)
  • AI辅助开发:让快马平台的AI帮你用min(公益版)实现表单智能验证
  • 华为OD机考双机位C卷 - 取出尽可能少的球(Java Python JS GO C++ C)
  • Python实战:3种文本特征提取方法对比(One-Hot vs TF-IDF vs Word2Vec)
  • Z-Image-Turbo作品集分享:看看8步生成的写实图片有多惊艳
  • Flutter 三方库 docker_process 的鸿蒙化适配指南 - 实现 Dart 对容器的精密控制、提升鸿蒙开发环境自动化效能
  • 3行代码搞定气象GRIB数据解析:pygrib如何突破格式壁垒?
  • 华为OD机考双机位C卷 - 基站维修工程师(Java Python JS GO C++ C)
  • Live2D模型资源解析技术全指南:从原理到实践的完整路径
  • 滚动轴承故障诊断实战:5分钟掌握4种特征频率计算公式(附Excel模板)
  • 亚洲美女-造相Z-Turbo入门必看:如何将生成图直接嵌入Notion/Airtable自动化工作流
  • 告别重复编码:快马AI自动生成Java基础开发高效工具模板
  • 颠覆式STM32开发:图形化编程如何革新嵌入式开发流程
  • 【仅限头部金融客户内部流出】MCP同步性能黄金参数表(覆盖K8s DaemonSet/边缘IoT/跨AZ三大部署拓扑)
  • Kafka Eagle 2.0.0保姆级安装指南:从解压到配置全流程详解
  • Mac/Win双平台保姆级教程:Android NDK r18b环境搭建全流程(含WSL配置)
  • 科研图表美化指南:R语言boxplot显著性标记的5个常见问题与解决方案
  • Spring Boot 缓存架构:一行配置切换 Caffeine 与 Redis,透明支持多租户隔离
  • Figma中文界面解决方案:提升设计效率的全流程指南
  • 告别月度账单惊吓!用VS Code插件实现MCP策略“编写即生效、提交即审计、推送即扣减”——已验证于日均2.4万容器集群
  • Live2D模型资源解析全流程实战指南:从原理到应用的深度探索
  • 解码器(Decoder)
  • AnimateDiff生成效果实测:看看这些文字描述能变成多美的视频
  • 3种突破:图形化编程重构STM32开发流程
  • ESP32-WROOM-32E + Node-RED实战:5分钟搞定物联网数据面板(附完整代码)
  • [特殊字符]️Qwen2.5-VL-7B-Instruct部署教程:Air-gapped离线环境全链路安装指南
  • QT自定义事件实战:从注册到处理的全流程指南(附多线程示例)
  • OpenWebUI+cpolar打造超顺手本地 AI 模型!
  • Keil5开发环境模拟:探讨嵌入式设备部署轻量级StructBERT的可行性
  • 开源技术赋能老旧设备:价值重构与效能优化全指南