代码随想录算法训练营第36期DAY44

DAY44

闫氏DP

2 01背包问题

用滚动数组来优化空间,从后向前(大到小)遍历j

  1. #include<iostream>
  2. using namespace std;
  3. const int N=1010;
  4. int n,m;
  5. int v[N],w[N];
  6. int f[N][N];//所有只考虑前i个物品,**且总体积不超过j**的选法的集合。
  7. int main(){
  8.     cin>>n>>m;
  9.     //背包当前体积j 是第二维度
  10.     for(int i=1;i<=n;i++)cin>>v[i]>>w[i];
  11.     for(int i=1;i<=n;i++){
  12.         //从0开始检查:前i个物体,使得背包体积为0,合法吗:合法,因为可以都不选
  13.         for(int j=0;j<=m;j++){
  14.             f[i][j]=f[i-1][j]; //left;
  15.             //右半边不一定存在,当前体积小于v[i],但是i又在背包。矛盾,不合法
  16.             //这里因为只计算变的情况下对应的当前背包体积,所以是[j-v[i]]
  17.             if(j>=v[i])f[i][j]=max(f[i][j],f[i-1][j-v[i]]+w[i]);
  18.         }
  19.     }
  20.     cout<<f[n][m]<<endl;
  21.     return 0;
  22. }

空间优化:

  1. #include<iostream>
  2. using namespace std;
  3. const int N=1010;
  4. int n,m;
  5. int v[N],w[N];
  6. int f[N];//所有只考虑前i个物品,**且总体积不超过j**的选法的集合。
  7. int main(){
  8.     cin>>n>>m;
  9.     //背包当前体积j 是第二维度
  10.     for(int i=1;i<=n;i++)cin>>v[i]>>w[i];
  11.     for(int i=1;i<=n;i++)
  12.         //从0开始检查:前i个物体,使得背包体积为0,合法吗:合法,因为可以都不选
  13.         for(int j=m;j>=v[i];j--)
  14.          f[j]=max(f[j],f[j-v[i]]+w[i]);
  15.     cout<<f[m]<<endl;
  16.     return 0;
  17. }

优化思想:代码等价即可。

完全背包问题

记:把01背包问题改成for(int j=v[i];j<=m;j++)即可

笔记见纸质版。

J=0 或j=1起步都可以

  1. #include<iostream>
  2. using namespace std;
  3. const int N=1010;
  4. int n,m;
  5. int v[N],w[N];
  6. int f[N][N];
  7. int main(){
  8.     cin>>n>>m;
  9.     for(int i=1;i<=n;i++) cin>>v[i]>>w[i];
  10.     for(int i=1;i<=n;i++){
  11.         for(int j=1;j<=m;j++){
  12.             f[i][j]=f[i-1][j];
  13.             if(j>=v[i]) f[i][j]=max(f[i][j],f[i][j-v[i]]+w[i]);
  14.         }
  15.     }
  16.     cout<<f[n][m]<<endl;
  17.     return 0;
  18. }

01背包问题 二维

  1. 暴力法:回溯

回溯算法--01背包问题_回溯法01背包问题-CSDN博客

学过了吗:学好了,但是和代码随想录的回溯模板不一样,不太适应。比较陌生,看来需要二刷回溯。

  1. 二维数组法:
  1. #include<iostream>
  2. using namespace std;
  3. const int N=5010;
  4. int v[N],w[N];
  5. int dp[N][N];
  6. int n,m;
  7. int main(){
  8.     cin>>n>>m;
  9.     for(int i=1;i<=n;i++) cin>>v[i];
  10.     for(int i=1;i<=n;i++) cin>>w[i];
  11.     
  12.     for(int i=1;i<=n;i++){
  13.         for(int j=0;j<=m;j++){
  14.             dp[i][j]=dp[i-1][j];
  15.             if(j>=v[i]) dp[i][j]=max(dp[i][j],dp[i-1][j-v[i]]+w[i]);
  16.         }
  17.     }
  18.     cout<<dp[n][m];
  19.     return 0;
  20. }

  1. 滚动数组优化
  1. #include<iostream>
  2. using namespace std;
  3. const int N=5010;
  4. int v[N],w[N];
  5. int dp[N];
  6. int n,m;
  7. int main(){
  8.     cin>>n>>m;
  9.     for(int i=1;i<=n;i++) cin>>v[i];
  10.     for(int i=1;i<=n;i++) cin>>w[i];
  11.     
  12.     for(int i=1;i<=n;i++){
  13.         for(int j=m;j>=v[i];j--){
  14.             dp[j]=max(dp[j],dp[j-v[i]]+w[i]);
  15.         }
  16.     }
  17.     cout<<dp[m];
  18.     return 0;
  19. }

01背包问题 一维

也就是3.滚动数组优化

416分割等和子集

  1. 贪心法,做不了,看例子:

  1. 动态规划:据说是01背包的应用,但是我想不出来怎么应用

这样想(也是我没想出来的点):两个子集的各自sum相等,那么它们的SUM应当等于原集合sum/2

// 每一个元素一定是不可重复放入,所以从大到小遍历

01背包问题:动态规划的思路一个一个物品去尝试,一点点扩大考虑能够容纳的容积大小,整个过程像是在填一张二维表格。

这题:设置状态:dp[i][j]表示考虑下标[0,i]这个区间里的所有整数,在它们当中是否能够选出一些数,使得这些数之和恰好为整数j。

优质题解,还分享了很多资料。

注意闫氏DP法的运用:在声明数组含义时候,需要明白每个下标的含义,然后再去denote DP数组的含义——满足**条件(每个下标)的**,再表示它的值。

学了很久,终于开始写代码了,见证自己的毅力哈哈:

  1. class Solution {
  2. public:
  3.     //代码随想录解法:能用一维就用一维,语句复杂反而不容易通过。
  4.     bool canPartition(vector<int>& nums) {
  5.         int sum=0;
  6.         for(auto n:nums) sum+=n;
  7.         if(sum%2==1return false;
  8.         sum/=2;
  9.         vector<intdp(20010,0);
  10.         for(int i=0;i<nums.size();i++){
  11.             for(int j=sum;j>=nums[i];j--){
  12.               dp[j]=max(dp[j],dp[j-nums[i]]+nums[i]);
  13.             }
  14.         }
  15.         return dp[sum]==sum;
  16.     }
  17. };

  1. class Solution {
  2. public:
  3. //二维力扣题解:
  4.     bool canPartition(vector<int>& nums) {
  5.         int sum=0;
  6.         for(int n:nums) sum+=n;
  7.         if(sum%2==1return false;
  8.         sum/=2;
  9.         int len=nums.size();
  10.         vector<vector<bool>> dp(len,vector<bool>(sum+1,false));
  11.         for(int i=0;i<len;i++) {
  12.             dp[i][0]=true;
  13.         }
  14.         if(sum>=nums[0]) dp[0][nums[0]]=true;
  15.         //这里下标有细节,配合上一句一起用,那么i从1开始
  16.         for(int i=1;i<len;i++){
  17.             for(int j=0;j<=sum;j++)
  18.             {
  19.                 //别写错
  20.                 dp[i][j]=dp[i-1][j];
  21.                 if(j>=nums[i]) dp[i][j]=dp[i][j]||dp[i-1][j-nums[i]];
  22.             }
  23.         }
  24.         return dp[nums.size()-1][sum];
  25.     }
  26. };

  1. class Solution {
  2. public:
  3. //力扣官方+一维滚动数组
  4.     bool canPartition(vector<int>& nums) {
  5.         int sum=0,max=INT_MIN;
  6.         for(auto n:nums) {
  7.             sum+=n;
  8.             if(n>max) max=n;
  9.         }
  10.         if(sum%2==1return false;
  11.         sum/=2;
  12.         if(max>sum) return false;
  13.         vector<booldp(sum+1,false);
  14.         dp[0]=true;
  15.         //照抄上一行,所以是i=1开始
  16.         for(int i=1;i<nums.size();i++){
  17.             //从后向前遍历
  18.             for(int j=sum;j>=nums[i];j--)
  19.             dp[j]=dp[j]||dp[j-nums[i]];
  20.         }
  21.         return dp[sum];
  22.     }
  23. };

  1. class Solution {
  2. public:
  3.     // 精选题解:
  4.     bool canPartition(vector<int>& nums) {
  5.         int sum = 0;
  6.         for (auto n : nums)
  7.             sum += n;
  8.         if (sum % 2 == 1)
  9.             return false;
  10.         sum /= 2;
  11.         vector<vector<bool>> dp(nums.size(), vector<bool>(sum + 1false));
  12.         if (sum >= nums[0])
  13.             dp[0][nums[0]] = true;
  14.         for (int i = 1; i < nums.size(); i++) {
  15.             for (int j = 0; j <= sum; j++) {
  16.                 dp[i][j] = dp[i-1][j];
  17.                 if (nums[i] == j) {
  18.                     dp[i][j] = true;
  19.                     continue;
  20.                 }
  21.                 if (j > nums[i])
  22.                     dp[i][j] = dp[i][j] || dp[i-1][j - nums[i]];
  23.             }
  24.         }
  25.         return dp[nums.size() - 1][sum];
  26.     }
  27. };

  1. class Solution {
  2. public:
  3.     // 精选题解:
  4.     bool canPartition(vector<int>& nums) {
  5.         int sum = 0;
  6.         for (auto n : nums)
  7.             sum += n;
  8.         if (sum % 2 == 1)
  9.             return false;
  10.         sum /= 2;
  11.         vector<vector<bool>> dp(nums.size(), vector<bool>(sum + 1false));
  12.         if (sum >= nums[0])
  13.             dp[0][nums[0]] = true;
  14.         for (int i = 1; i < nums.size(); i++) {
  15.             for (int j = 0; j <= sum; j++) {
  16.                 dp[i][j] = dp[i-1][j];
  17.                 if (nums[i] == j) {
  18.                     dp[i][j] = true;
  19.                     continue;
  20.                 }
  21.                 if (j > nums[i])
  22.                     dp[i][j] = dp[i][j] || dp[i-1][j - nums[i]];
  23.                 if(dp[i][sum]) return true;
  24.             }
  25.         }
  26.         return dp[nums.size() - 1][sum];
  27.     }
  28. };

  1. class Solution {
  2. public:
  3.     // 精选题解:
  4.     bool canPartition(vector<int>& nums) {
  5.         int sum = 0;
  6.         for (auto n : nums)
  7.             sum += n;
  8.         if (sum % 2 == 1)
  9.             return false;
  10.         sum /= 2;
  11.         vector<booldp(sum+1false);
  12.         dp[0] = true;
  13.         //下一句不能少:他作为第一行
  14.         if(sum>=nums[0]) dp[nums[0]]=true;
  15.         for (int i = 1; i < nums.size(); i++) {
  16.             for (int j = sum; j >= nums[i]; j--) {
  17.                  dp[j] = dp[j] || dp[j - nums[i]];
  18.             }
  19.         }
  20.         return dp[sum];
  21.     }
  22. };

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/19458.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

趋势分析:2024年 2D CAD 在工业工程软件中的市场现状

文章概览 CAD发展趋势 一、现状 二、2D CAD在工业工程规划软件中的作用 三、工业工程师使用什么软件&#xff1f; 四、DraftSight&#xff1a;功能强大的工业工程软件 实际工业工程应用 一、ERIKS&#xff1a;使用 DraftSight 管理大量 2D 图纸 二、Sealed Air&#xff1…

过敏者的福音:猫毛克星大揭秘!使用宠物空气净化器效果如何?

对于猫毛过敏者来说&#xff0c;家中爱宠的陪伴与过敏的困扰并存&#xff0c;给他们的日常生活带来了极大的不便。猫毛过敏者常常因为与猫咪接触后出现打喷嚏、鼻塞、眼睛发痒等症状而苦恼&#xff0c;严重时甚至可能影响到他们的呼吸健康。 然而&#xff0c;这并不意味着猫毛…

JavaWeb笔记整理+图解——Filter过滤器

欢迎大家来到这一篇章——Filter过滤器 监听器和过滤器都是JavaWeb服务器三大组件(Servlet、监听器、过滤器)之一,他们对于Web开发起到了不可缺少的作用。 ps:想要补充Java知识的同学们可以移步我已经完结的JavaSE笔记,里面整理了大量详细的知识点和图解,可以帮你快速掌…

精益管理|AIRIOT智慧变电站管理解决方案

随着社会电气化进程的加速&#xff0c;电力需求与日俱增&#xff0c;变电站作为电网的关键节点&#xff0c;其稳定性和智能化管理水平直接关系到整个电力系统的高效运作。传统变电站管理平台难以适应现代电力系统复杂管理需求&#xff0c;存在如下痛点&#xff1a; 数据收集与…

【机器学习】深入探索机器学习:利用机器学习探索股票价格预测的新路径

❀机器学习 &#x1f4d2;1. 引言&#x1f4d2;2. 多种机器学习算法的应用&#x1f4d2;3. 机器学习在股票价格预测中的应用现状&#x1f389;数据收集与预处理&#x1f389;模型构建与训练&#x1f308;模型评估与预测&#x1f31e;模型评估&#x1f319;模型预测⭐注意事项 &…

Python 机器学习 基础 之 算法链与管道 【通用的管道接口/网格搜索预处理步骤与模型参数/网格搜索选择使用哪个模型】的简单说明

Python 机器学习 基础 之 算法链与管道 【通用的管道接口/网格搜索预处理步骤与模型参数/网格搜索选择使用哪个模型】的简单说明 目录 Python 机器学习 基础 之 算法链与管道 【通用的管道接口/网格搜索预处理步骤与模型参数/网格搜索选择使用哪个模型】的简单说明 一、简单介…

留言板——增添功能(持久化存储数据,使用MyBatis)

目录 一、数据准备 二、引入MyBatis 和 MySQL驱动依赖 三、配置MySQL账号密码 四、编写后端代码 五、调整前端代码 六、测试 之前的代码&#xff1a;综合性练习&#xff08;后端代码练习3&#xff09;——留言板_在线留言板前后端交互-CSDN博客 一、数据准备 创建数据库…

公司生产环境AWX配置的操作与部署说明

一、模板 模板名称&#xff0c;见名知义项目&#xff1a;ansible脚本所在的位置&#xff0c;可以是本地&#xff0c;也可以是远程分布式配置&#xff0c;比如gitlab。&#xff08;详见下文&#xff09;PLAYBOOK&#xff1a;ansible运行的入口凭证作业标签&#xff1a;任务的细分…

2024 RCTF WebMisc部分 WP

Misc gogogo 考点:内存取证 得到 gogogo.raw 内存取证的题用volatility和AXIOM结合分析 AXIOM 分析存在云服务 但是百度网盘要密码 https://pan.baidu.com/share/init?surlZllFd8IK-oHvTCYl61_7Kw 发现访问过sqlite数据库 可以尝试提取数据库文件出来 结合 volatility 第…

知识库管理系统:是什么、作用、如何搭建

你有没有遇到过这种情况&#xff1a;在工作中想要查找某个信息&#xff0c;查找了很多个文档还是没找到准确的信息&#xff1b;或者在团队中&#xff0c;总是在重复做着相同的资料搜集工作&#xff0c;浪费了大量时间和精力&#xff1f;如果你在烦恼这个问题&#xff0c;那么跟…

替换字符串

自学python如何成为大佬(目录):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 sub()方法用于实现字符串替换&#xff0c;语法格式如下&#xff1a; re.sub(pattern, repl, string, count, flags) 参数说明&#xff1a; l pat…

软件测试可发现所有bug吗?有什么样的原则和目的?

在今天的高度数字化时代&#xff0c;软件测试的重要性不可忽视。这是一种系统性的过程&#xff0c;通过对软件系统进行评估和验证&#xff0c;以确定其是否满足预期要求。在软件开发的各个阶段&#xff0c;软件测试都扮演着至关重要的角色。它涉及到软件功能、性能、安全性等多…

在CentOS系统上安装Oracle JDK(华为镜像)

在CentOS系统上安装Oracle JDK(华为镜像) 先爱上自己&#xff0c;再遇见爱情&#xff0c;不庸人自扰&#xff0c;不沉溺过去&#xff0c;不为自己的敏感而患得患失&#xff0c;不为别人的过失而任性&#xff0c;这才是终身浪漫的开始。 https://repo.huaweicloud.com/java/jdk …

C++学习第十一天——vector的模拟实现

✨ 生于火焰&#xff0c;落俗不可避免&#xff0c;但浪漫至死不渝 &#x1f30f; &#x1f4c3;个人主页&#xff1a;island1314 &#x1f525;个人专栏&#xff1a;C学习 &#x1f680; 欢迎关注&#xff1a;&#x1f44d;点赞 &…

DevExpress开发WPF应用实现对话框总结

说明&#xff1a; 完整代码Github​&#xff08;https://github.com/VinciYan/DXMessageBoxDemos.git&#xff09;DevExpree v23.2.4&#xff08;链接&#xff1a;https://pan.baidu.com/s/1eGWwCKAr8lJ_PBWZ_R6SkQ?pwd9jwc 提取码&#xff1a;9jwc&#xff09;使用Visual St…

基于Spring前后端分离版本的论坛系统-自动化测试

目录 前言 一、测试环境 二、环境部署 三、测试用例 四、执行测试 4.1、公共类设计 创建浏览器驱动对象 测试套件 释放驱动类 4.2、功能测试 注册页面 登录页面 版块 帖子 用户个人中心页 站内信 4.3、界面测试 注册页面 登录页面 版块 帖子 用户个人中心页…

Redis实战篇3:优惠券秒杀

说明 该实战篇基于某马的Redis课程中的《某马点评项目》。非常适合有相关经验、缺少企业级解决方案&#xff0c;或者想要复习的人观看&#xff0c;全篇都会一步一步的推导其为什么要这么做&#xff0c;分析其优缺点&#xff0c;达到能够应用的地步。 本实战篇中心思想就是把项目…

Mariadb操作命令指南

MariaDB简介 ​ 以下内容仅是站长或网友个人学习笔记、总结和研究收藏。不保证正确性&#xff0c;因使用而带来的风险与本站无关&#xff01; 数据库应用程序与主应用程序分开存在&#xff0c;并存储数据集合。 每个数据库都使用一个或多个API来创建&#xff0c;访问&#xf…

分立元件实现稳压

电路原理图 优点&#xff1a;电压精度高&#xff0c;可以调整输出电压 缺点&#xff1a;压差大时效率较低&#xff0c;发热严重。 参考连接 TL431-高效5V精密稳压器-电路知识干货 (qq.com)https://mp.weixin.qq.com/s?__bizMzkxNzIxNTc5OQ&mid2247484878&idx1&…

操作系统教材第6版——个人笔记1

第一章 计算机操作系统概述 操作系统是计算机系统中最重要的系统软件&#xff0c;它统一管理计算机系统的硬件资源与信息资源&#xff0c;控制与调度上层软件的执行并为其提供易于使用的接口。从资源管理、程序控制、操作控制、人机交互、程序接口、系统结构6个角度深入观察操…