代码随想录算法训练营第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. };

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【原创】springboot+mysql医院预约挂号管理系统设计与实现

个人主页&#xff1a;程序猿小小杨 个人简介&#xff1a;从事开发多年&#xff0c;Java、Php、Python、前端开发均有涉猎 博客内容&#xff1a;Java项目实战、项目演示、技术分享 文末有作者名片&#xff0c;希望和大家一起共同进步&#xff0c;你只管努力&#xff0c;剩下的交…

禁止Windows Defender任务计划程序

开始键->搜索“任务计划程序”->“任务计划程序库”->“Microsoft”->"Windows"->"Windows Defender"->右边四项

【Redis】List源码剖析

大家好&#xff0c;我是白晨&#xff0c;一个不是很能熬夜&#xff0c;但是也想日更的人。如果喜欢这篇文章&#xff0c;点个赞&#x1f44d;&#xff0c;关注一下&#x1f440;白晨吧&#xff01;你的支持就是我最大的动力&#xff01;&#x1f4aa;&#x1f4aa;&#x1f4aa…

Scrapy vs. Beautiful Soup | 网络抓取教程 2024

网络爬虫是任何想要从网上收集数据用于分析、研究或商业智能的人必备的技能。Python中两个最受欢迎的网络爬虫工具是Scrapy和Beautiful Soup。在本教程中&#xff0c;我们将比较这些工具&#xff0c;探索它们的功能&#xff0c;并指导你如何有效地使用它们。此外&#xff0c;我…

文件系统小册(FusePosixK8s csi)【2 Posix标准】

文件系统小册&#xff08;Fuse&Posix&K8s csi&#xff09;【2 Posix】 往期文章&#xff1a;文件系统小册&#xff08;Fuse&Posix&K8s csi&#xff09;【1 Fuse】 POSIX&#xff1a;可移植操作系统接口&#xff08;标准&#xff09; 1 概念 POSIX&#xff1a;…

Linux 编译安装python

以deepin操作系统安装Python3.8.10为例。 下载 python3.8.10 官网下载 Linux要下载源码&#xff0c;进行编译。 下图tarball即tar包&#xff0c;是压缩包的意思。python官网给出两种压缩格式的tarball&#xff0c;下载哪个都可以。 方式一&#xff1a;直接点击链接下载 方式…

2.7HDR与LDR

一、基本概念 1.基本概念 动态范围&#xff08;Dynamic Range&#xff09; 最高亮度 / 最低亮度 HDR High Dynamic RangeLDR Low Dynamic Range HDR与LDR和Tonemapping的对应关系&#xff1a; 我们常用的各种显示器屏幕&#xff0c;由于不同的厂家不同的工艺导致它们的…

【经典排序算法】堆排序(精简版)

什么是堆排序&#xff1a; 堆排序(Heapsort)是指利用堆&#xff08;完全二叉树&#xff09;这种数据结构所设计的一种排序算法&#xff0c;它是选择排序的一种。需要注意的是排升序要建大堆&#xff0c;排降序建小堆。 堆排序排序的特性总结&#xff1a; 1. 堆排序使用堆来选数…

建议收藏-各类IT证书查验真伪链接

1、红帽认证证书核验链接&#xff1a; https://rhtapps.redhat.com/verify/ RHCSA认证、RHCE认证、RHCA认证 添加图片注释&#xff0c;不超过 140 字&#xff08;可选&#xff09; 2、华为认证证书核验链接&#xff1a; https://e.huawei.com/cn/talent/#/cert/certificate…

js:flex弹性布局

目录 代码&#xff1a; 1、 flex-direction 2、flex-wrap 3、justify-content 4、align-items 5、align-content 代码&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewp…

Vue3-Ref Reactive toRef toRefs对比学习

响应式数据&#xff1a; Ref 作用&#xff1a;定义响应式变量。 语法&#xff1a;let xxx ref(初始值)(里面可以是任何规定内类型、数组等)。 返回值&#xff1a;一个RefImpl的实例对象&#xff0c;简称ref对象或ref&#xff0c;ref对象的value属性是响应式的。 注意点&am…

Keil 5恢复默认布局,左边状态栏

第一步&#xff0c;点击windows&#xff1a; 第二步&#xff0c;点击reset view to default&#xff1a; 第三步&#xff0c;点击reset即可&#xff1a;

少样本学习与零样本学习:理解与应用

少样本学习与零样本学习&#xff1a;理解与应用 在现代机器学习领域中&#xff0c;少样本学习&#xff08;Few-Shot Learning&#xff09;和零样本学习&#xff08;Zero-Shot Learning&#xff09;正变得越来越重要。这些技术能够在数据稀缺的情况下有效地进行学习和推理&…

ARC学习(2)基本编程模型认识(二)

笔者继续来学习一下arc的编程模型的寄存器信息。 1、core寄存器深入 参数寄存器&#xff1a;r0-r7&#xff0c;8个参数&#xff0c;暂存器&#xff1a;r10-r15保存寄存器&#xff1a;r16-r25 调用函数需要保存的寄存器指针寄存器&#xff1a;gp&#xff08;全局指针&#xff09…

基于大模型的智慧零售教育科研平台——技术方案

一、概述 1.1背景 随着数字经济的快速发展和全社会数字化水平的升级&#xff0c;人工智能的积极作用越来越凸显&#xff0c;人工智能与各个行业的深度融合已成为促进传统产业转型升级的重要方式之一。ChatGPT的出现掀起了又一波人工智能发展热潮&#xff0c;人工智能行业发展势…

法线方程实现最小二乘拟合(Matlab)

一、问题描述 利用法线方程实现最小二乘拟合。 二、实验目的 掌握法线方程方法的原理&#xff0c;能够利用法线方程完成去一组离散数据点的拟合。 三、实验内容及要求 对于下面的不一致系统&#xff0c;构造法线方程&#xff0c;计算最小二乘以及2-范数误差。 [ 3 − 1 2 …

国产飞腾/龙芯/瑞芯微芯片在信创行业应用:金融行业、教育行业、党政机关

党政机构 方案背景&#xff1a; 在国家提出信息技术应用创新发展战略的大环境下&#xff0c;政务大厅需要基于国家科技自主技术深入推进“互联网政务服务”。加快建设全国一体化在线政务服务平台&#xff0c;进一步落实创新驱动发展战略&#xff0c;提升政务网络安全保障能力…

Java筑基—String类

这里写目录标题 一、字符串的拼接二、获取字符串长度三、字符串转换四、去除前后空白字符五、比较字符串是否相等六、比较字符串是否包含七、字符串是否以某些开始、结尾八、字符串的替换九、字符串的转换十、空串和NULL串 一、字符串的拼接 Java语言允许使用 号拼接两个字符…

内网不能访问域名怎么办?

在网络应用中&#xff0c;我们常常遇到内网不能访问域名的问题。这是由于内网环境限制导致的&#xff0c;内网无法直接连接到公网&#xff0c;因而无法访问互联网上的域名。我们可以利用一些特殊技术和工具来解决这个问题。 天联组网技术的应用 天联组网是一种非常受欢迎的解决…

IDEA启动jsp项目

1、背景 有个老项目的前端需要修改&#xff0c;整来源码之后发现是比较古老的jsp项目&#xff0c;需要在idea中启动下试试 2、代码配置流程 常规的配置流程网上都有 2.1 首先找到Project Structure 2.2 配置web.xml 注意下方的 web resource directory, web.xml中的写的相对…