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

算法训练营第四十二天|动态规划:01背包理论基础 416. 分割等和子集

目录

  • 动态规划:01背包理论基础
  • 416. 分割等和子集

动态规划:01背包理论基础

文章链接:代码随想录
题目链接:卡码网:46. 携带研究材料

01背包问题
二维数组解法:

#include <bits/stdc++.h>
using namespace std;void slove(int M, int N){vector<vector<int>> dp(M, vector<int> (N + 1));vector<int> weight(M), value(M);for (int i = 0; i < M; i++){cin >> weight[i];}for (int i = 0; i < M; i++){cin >> value[i];}for (int j = 0; j <= N; j++){if (j >= weight[0]) dp[0][j] = value[0];}for (int i = 1; i < M; i++){for (int j = 0; j <= N;  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[M - 1][N] << endl;
}int main(){int M, N;cin >> M >> N;slove(M, N);return 0;
}

思路:就是按代码随想录上的那张二维表来看,更新 j 重量下的背包能放0 - i 中多少最大价值的物品;然后一行一行的更新,更新到新物品时,要么就是在 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]);

其中,

dp[i - 1][j]

代表不放入 i 物品

dp[i - 1][j - weight[i]] + value[i]

代表在 j 重量下先空出weight[i]这么大的空间,然后再放如 i 物品,它可能是本来就有这么大空间,也可能是把其它一些物品拿出去后再放入的 i 物品。

一维(滚动数组)数组解法:

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

一维数组相比二维数组解法就是将每次更新都放在一行上,而且省去了初始化,所以会节省很多空间,这点在后面 leetcode 上的那题会看到比较。另外要注意在遍历重量时是倒序遍历的:

dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);

正序遍历会引起重复,而二维数组不会重复是因为每行都用的是上一行的值来更新的。
第一天理解的时候迷迷糊糊,第二天没事时有想了一会突然茅塞顿开了哈哈哈。

416. 分割等和子集

文章链接:代码随想录
题目链接:416. 分割等和子集

思路:01背包应用问题,留足背包的容量,也就是最大总和的一半值加一,如果更新到最后在半值重量的背包中能正好装满,就说明数组可以对半分。
二维数组解法:

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

一维(滚动)数组解法:

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


这里可以看出两种解法的时间空间对比,显然二维解法有着更大的时间和空间复杂度。因此以后的应用问题尽可能一维(滚动)数组解法。

第四十二天补卡,这两天回学校吃组饭,又耽误了两天,后面那顿饭你不行不去吃了;大体知识能串联起来了,今天开始撸项目背八股,哪不会学哪了,单学效率太低了,争取能在春节后找到个实习,加油!!!

http://www.lryc.cn/news/277897.html

相关文章:

  • 前端 JS篇快问快答
  • vue/vue3/js来动态修改我们的界面浏览器上面的文字和图标
  • MobaXterm SSH 免密登录配置
  • 霍兰德职业兴趣测试:找到与你性格匹配的职业
  • LVGL学习笔记 显示和隐藏 对象的属性标志位 配置
  • cuda上使用remap函数
  • 【JaveWeb教程】(18) MySQL数据库开发之 MySQL数据库设计-DDL 如何查询、创建、使用、删除数据库数据表 详细代码示例讲解
  • ElasticSearch学习笔记-SpringBoot整合Elasticsearch7
  • [足式机器人]Part2 Dr. CAN学习笔记 - Ch02动态系统建模与分析
  • 【一周年创作总结】人生是远方的无尽旷野呀
  • 金融帝国实验室(Capitalism Lab)V10版本游戏平衡性优化与改进
  • [SpringBoot]接口的多实现:选择性注入SpringBoot接口的实现类
  • 北京大学 wlw机器学习2022春季期末试题分析
  • 前端文件下载方法(包含get和post)
  • 高性能、可扩展、支持二次开发的企业电子招标采购系统源码
  • 2645. 构造有效字符串的最少插入数
  • C#,快速排序算法(Quick Sort)的非递归实现与数据可视化
  • 【操作系统xv6】学习记录2 -RISC-V Architecture
  • C++力扣题目111--二叉树的最小深度
  • 【图像拼接】源码精读:Adaptive As-Natural-As-Possible Image Stitching(AANAP/ANAP)
  • 解决docker run报错:Error response from daemon: No command specified.
  • 算法第十二天-最大整除子集
  • 简单易懂的PyTorch 损失函数:优化机器学习模型的关键
  • Kubernetes/k8s的存储卷/数据卷
  • 【漏洞复现】锐捷RG-UAC统一上网行为管理系统信息泄露漏洞
  • Android - 串口通讯(SerialPort)
  • 如何使用設置靜態住宅IP
  • 在学习爬虫前的准备
  • windows下安装oracle-win-64-11g超详细图文步骤
  • Go模板后端渲染时vue单页面冲突处理