算法日记27:完全背包(DFS->记忆化搜索->倒叙DP->顺序DP->空间优化)

一、暴力搜索(DFS) O ( n 2 ) O(n^2) O(n2)
1.1)思路解析
1、注意和01背包的区别在于每个物品可以无限次选择
- 注意在完全背包中,当一个物品被选择过一次,我们仍然需要考虑是否继续选择这个物品
- 01背包:
max(dfs(x + 1, Spv), dfs(x + 1, Spv - vi[x]) + wi[x])//不选/选 - 完全背包:
max(dfs(x+1,Spv),dfs(x,Spv-vi[x])+wi[x]) //不选/选
- 01背包:
2、注意当选这个物品的时候,下一次应该继续考虑这个物品是否继续选择,所以是dfs(x,Spv-vi[x])+wi[x]
1.2)代码解析
#include <bits/stdc++.h>
using namespace std;const int N = 1007;
int vi[N],wi[N];
int n, v;int dfs(int x, int Spv)//从第x件物品开始,当前剩余容量为Spv
{if(x>n) return 0;if(Spv<vi[x]) return dfs(x+1,Spv); //物品体积太大,选不了else return max(dfs(x+1,Spv),dfs(x,Spv-vi[x])+wi[x]);
}void solve()
{cin >> n >> v;for (int i = 1; i <= n; i++){cin >> vi[i]>>wi[i];}int res=dfs(1,v);cout<<res<<'\n';
}int main()
{ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);int _ =1; //cin >> _;while (_--) solve();system("pause");return 0;
}
二、记忆化搜索 O ( n ∗ v ) O(n*v) O(n∗v)
2.1)思路解析
1、相比所谓的暴力搜索,优化了大量的时间复杂度(指数级->线性级)
2、所谓记忆化搜索,就是把DFS计算过的数据不再重复计算(用一个mem数组存储状态)
PS :记忆化数组的数据个数一般和DFS函数的参数一致
2.2)代码解析
#include <bits/stdc++.h>
using namespace std;const int N = 1007;
int vi[N],wi[N];
int n, v;
int mem[N][N];int dfs(int x, int Spv)//从第x件物品开始,当前剩余容量为Spv
{if(mem[x][Spv]) return mem[x][Spv];if(x>n) return 0;if(Spv>=vi[x]) //表示可以选{//选/不选return mem[x][Spv]=max(dfs(x,Spv-vi[x])+wi[x],dfs(x+1,Spv));}else //空间不够,不能拿当前物品{return mem[x][Spv]=dfs(x+1,Spv);}
}void solve()
{cin >> n >> v;for (int i = 1; i <= n; i++){cin >> vi[i]>>wi[i];}cout<<dfs(1,v)<<'\n';
}int main()
{ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);int _ =1; //cin >> _;while (_--) solve();system("pause");return 0;
}
三、倒序动态规划
3.1)思路解析
1、典型的空间换时间的做法,相比于搜索,节约了大量的时间复杂度
2、动态规划的for循环变量的参数,应该与DFS边界的限制的参数相同(例如:本题目中,边界与物品数量X、剩余的体积SPV有关)所以循环为n/v作为参数
- 因为在递归中,只有归才是产生答案的过程,所以可以从边界直接开始推出答案
3.2)代码解析
#include <bits/stdc++.h>
using namespace std;const int N = 1007;
int vi[N],wi[N];
int n, v;
int mem[N][N];
int f[N][N];// int dfs(int x, int Spv)//从第x件物品开始,当前剩余容量为Spv
// {
// if(mem[x][Spv]) return mem[x][Spv];
// if(x>n) return 0;// if(Spv>=vi[x]) //表示可以选
// {
// //选/不选
// return mem[x][Spv]=max(dfs(x,Spv-vi[x])+wi[x],dfs(x+1,Spv));
// }
// else //空间不够,不能拿当前物品
// {
// return mem[x][Spv]=dfs(x+1,Spv);
// }
// }void solve()
{cin >> n >> v;for (int i = 1; i <= n; i++){cin >> vi[i]>>wi[i];}//cout<<dfs(1,v)<<'\n';for(int i=1;i<=n;i++) //第几个物品{for(int j=0;j<=v;j++) //体积值{if(j>=vi[i]) 表示可以选f[i][j]=max(f[i-1][j],f[i][j-vi[i]]+wi[i]); //不选/选else //空间不够,不能拿当前物品f[i][j]=f[i-1][j];}}cout<<f[n][v];
}int main()
{ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);int _ =1; //cin >> _;while (_--) solve();system("pause");return 0;
}
四、顺序动态规划
4.1)思路解析
1、倒序遍历物品总是怪怪的,那么可不可以正序枚举呢,当然是可以的。
- PS:正序枚举相当于以 n − > 1 n->1 n−>1开始递归,此时边界刚刚好是为 1 1 1,所以循环从 1 1 1开始
4.2)代码解析
#include <bits/stdc++.h>
using namespace std;const int N = 1007;
int vi[N],wi[N];
int n, v;
int mem[N][N];
int f[N][N];// int dfs(int x, int Spv)//从第x件物品开始,当前剩余容量为Spv
// {
// if(mem[x][Spv]) return mem[x][Spv];// int sum=0;// if(x>n) sum= 0;
// else if(Spv<vi[x]) sum= dfs(x+1,Spv); //物品体积太大,选不了
// else sum= max(dfs(x+1,Spv),dfs(x,Spv-vi[x])+wi[x]);// mem[x][Spv]=sum;
// return sum;
// }void solve()
{cin >> n >> v;for (int i = 1; i <= n; i++){cin >> vi[i]>>wi[i];}for(int i=1;i<=n;i++) //变为正序递推{for(int j=0;j<=v;j++){if(j<vi[i]) f[i][j]=f[i-1][j]; //选不了else f[i][j]=max(f[i-1][j],f[i][j-vi[i]]+wi[i]); //不选/选}}cout<<f[n][v];
}int main()
{ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);int _ =1; //cin >> _;while (_--) solve();system("pause");return 0;
}
五、二维–>一维(空间优化)
5.1)思路解析
- 注意完全背包的二维的遍历应该是顺序枚举,为什么呢?
1、看下图,如果是正序的话,那么结果就会从:i 的状态–> i-1的状态
- 也就是从已经拿过第
i件商品的情况下,考虑在相同体积下是否要继续拿第i件商品
2、而物品 i i i的状态此时表明已经考虑过了 i i i这个物品,也就是已经选过了 i i i
3、那么此时就变成了从这个物品已经选过的状态—>下一个状态,那么此时,就表明这个物品就重复选了!!!,这就变成了完全背包!!!

5.2)代码解析
#include <bits/stdc++.h>
using namespace std;const int N = 1007;
int vi[N],wi[N];
int n, v;
int mem[N][N];
int f[N];// int dfs(int x, int Spv)//从第x件物品开始,当前剩余容量为Spv
// {
// if(mem[x][Spv]) return mem[x][Spv];
// if(x>n) return 0;// if(Spv>=vi[x]) //表示可以选
// {
// //选/不选
// return mem[x][Spv]=max(dfs(x,Spv-vi[x])+wi[x],dfs(x+1,Spv));
// }
// else //空间不够,不能拿当前物品
// {
// return mem[x][Spv]=dfs(x+1,Spv);
// }
// }void solve()
{cin >> n >> v;for (int i = 1; i <= n; i++){cin >> vi[i]>>wi[i];}//cout<<dfs(1,v)<<'\n';for(int i=1;i<=n;i++) //第几个物品{for(int j=0;j<=v;j++) //体积值{if(j>=vi[i]) f[j]=max(f[j],f[j-vi[i]]+wi[i]); //不选/选}}cout<<f[v];
}int main()
{ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);int _ =1; //cin >> _;while (_--) solve();system("pause");return 0;
}
总结:


相关文章:
算法日记27:完全背包(DFS->记忆化搜索->倒叙DP->顺序DP->空间优化)
一、暴力搜索(DFS) O ( n 2 ) O(n^2) O(n2) 1.1)思路解析 1、注意和01背包的区别在于每个物品可以无限次选择 注意在完全背包中,当一个物品被选择过一次,我们仍然需要考虑是否继续选择这个物品 01背包: …...
Linux 命令大全完整版(14)
5. 文件管理命令 chgrp(change group) 功能说明:变更文件或目录的所属群组。语 法:chgrp [-cfhRv][–help][–version][所属群组][文件或目录…] 或 chgrp [-cfhRv][–help][–version][–reference<参考文件或目录>][文件或目录…]补充说明&…...
基于 DeepSeek LLM 本地知识库搭建开源方案(AnythingLLM、Cherry、Ragflow、Dify)认知
写在前面 博文内容涉及 基于 Deepseek LLM 的本地知识库搭建使用 ollama 部署 Deepseek-R1 LLM知识库能力通过 Ragflow、Dify 、AnythingLLM、Cherry 提供理解不足小伙伴帮忙指正 😃,生活加油 我站在人潮中央,思考这日日重复的生活。我突然想,…...
Could not initialize class io.netty.util.internal.Platfor...
异常信息: Exception in thread "main" java.lang.NoClassDefFoundError: Could not initialize class io.netty.util.internal.PlatformDependent0 Caused by: java.lang.ExceptionInInitializerError: Exception java.lang.reflect.InaccessibleObjec…...
【书生大模型实战营】玩转HF/魔搭/魔乐社区-L0G4000
本文是书生大模型实战营系列的第4篇,本文的主题是:玩转HF/魔搭/魔乐社区。 1.开源大模型社区总览 开源不仅仅是一种技术模式,更是一种精神的体现。它打破了知识的壁垒,让技术平权成为可能。近年来,开源大模型社区蓬勃…...
2025年华为手机解锁BL的方法
注:本文是我用老机型测试的,新机型可能不适用 背景 华为官方已经在2018年关闭了申请BL解锁码的通道,所以华为手机已经无法通过官方获取解锁码。最近翻出了一部家里的老手机华为畅玩5X,想着能不能刷个系统玩玩,但是卡…...
了解 RAG 第二部分:经典 RAG 的工作原理
在本系列的第一篇文章中,我们介绍了检索增强生成 (RAG) ,解释了扩展传统大型语言模型 (LLM)功能的必要性。我们还简要概述了 RAG 的核心思想:从外部知识库检索上下文相关的信息,以确保 LLM 生成准确且最新的信息,而不会…...
50周学习go语言:第四周 函数与错误处理深度解析
第四周 函数与错误处理深度解析 以下是第4周函数基础的深度教程,包含两个完整案例和详细实现细节: 第四周:函数与错误处理深度解析 一、函数定义与参数传递 1. 基础函数结构 // 基本语法 func 函数名(参数列表) 返回值类型 {// 函数体 }// …...
debian 12安装 postgresql 17
按照官方文档安装,即可安装成功 https://www.postgresql.org/download/linux/debian/ 添加存储库 #添加存储库 sudo apt install -y postgresql-common#执行 存储库内 命令,自动处理某些东西 sudo /usr/share/postgresql-common/pgdg/apt.postgresql.o…...
C++....................4
1. using namespace std; class mystring { private:char* p;int len;// 辅助函数:复制字符串void copy(const char* source) {len strlen(source);p new char[len 1];strcpy(p, source);}// 辅助函数:释放内存void release() {if (…...
图书馆系统源码详解
本项目是一个基于Scala语言开发的图书馆管理系统。系统主要由以下几个部分组成:数据访问层(DAO)、数据模型层(Models)、服务层(Service)以及用户界面层(UI)。以下是对项目…...
Node.js中如何修改全局变量的几种方式
Node.js中如何修改全局变量。我需要先理解他们的需求。可能他们是在开发过程中遇到了需要跨模块共享数据的情况,或者想要配置一些全局可访问的设置。不过,使用全局变量可能存在一些问题,比如命名冲突、难以维护和测试困难,所以我得…...
基于javaweb的SpringBoot个人博客系统设计和实现(源码+文档+部署讲解)
技术范围:SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容:免费功能设计、开题报告、任务书、中期检查PPT、系统功能实现、代码编写、论文编写和辅导、论…...
厦大团队:DeepSeek大模型概念、技术与应用实践 140页PDF完整版下载
DeepSeek使用教程系列: 厦门大学: DeepSeek大模型概念、技术与应用实践 140页PDF完整版文件 厦大团队:DeepSeek大模型概念、技术与应用实践(140页PPT读懂大模型).pdf https://pan.baidu.com/s/1de4UIxqPsvMBIYcpen_M-…...
【Blender】二、建模篇--05,阵列修改器与晶格形变
阵列修改器是bender里面一个比较常用的修改器,所以我们单独开口来讲,我们会先从几片树叶出发,然后我们用阵列修改器把这几片树叶变成这样的造型和这样的造型。这两个造型分别就代表着阵列修改器最常用的两种偏移方法,我们现在就开始我们先来做几个树叶。 1.树叶建模 首先…...
#渗透测试#批量漏洞挖掘#畅捷通T+远程命令执行漏洞
免责声明 本教程仅为合法的教学目的而准备,严禁用于任何形式的违法犯罪活动及其他商业行为,在使用本教程前,您应确保该行为符合当地的法律法规,继续阅读即表示您需自行承担所有操作的后果,如有异议,请立即停止本文章读。 目录 一、漏洞概况 二、攻击特征 三、应急处置…...
【Python爬虫(23)】探秘Python爬虫数据存储:MongoDB实战指南
【Python爬虫】专栏简介:本专栏是 Python 爬虫领域的集大成之作,共 100 章节。从 Python 基础语法、爬虫入门知识讲起,深入探讨反爬虫、多线程、分布式等进阶技术。以大量实例为支撑,覆盖网页、图片、音频等各类数据爬取ÿ…...
Pytorch使用手册-音频数据增强(专题二十)
音频数据增强 torchaudio 提供了多种方式来增强音频数据。 在本教程中,我们将介绍一种应用效果、滤波器、RIR(房间脉冲响应)和编解码器的方法。 最后,我们将从干净的语音合成带噪声的电话语音。 import torch import torchaudio import torchaudio.functional as Fprin…...
Linux 命令大全完整版(04)
1. 用户信息相关命令 who 功能说明:显示目前登入系统的用户信息。语 法:who [-Himqsw][--help][--version][am i][记录文件]补充说明:执行这项指令可得知目前有哪些用户登入系统,单独执行 who 指令会列出登入帐号、使用的终端…...
嵌入式Linux内核底层调试技术Kprobes
大家好,我是bug菌~ Kprobes 是 Linux 内核中一种动态插桩(Dynamic Instrumentation)技术,允许在不修改内核源码或重启系统的前提下,动态监控内核函数的执行。它是内核调试、性能分析和安全监控的重要工具。以下从技术…...
铭豹扩展坞 USB转网口 突然无法识别解决方法
当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…...
第19节 Node.js Express 框架
Express 是一个为Node.js设计的web开发框架,它基于nodejs平台。 Express 简介 Express是一个简洁而灵活的node.js Web应用框架, 提供了一系列强大特性帮助你创建各种Web应用,和丰富的HTTP工具。 使用Express可以快速地搭建一个完整功能的网站。 Expre…...
day52 ResNet18 CBAM
在深度学习的旅程中,我们不断探索如何提升模型的性能。今天,我将分享我在 ResNet18 模型中插入 CBAM(Convolutional Block Attention Module)模块,并采用分阶段微调策略的实践过程。通过这个过程,我不仅提升…...
蓝牙 BLE 扫描面试题大全(2):进阶面试题与实战演练
前文覆盖了 BLE 扫描的基础概念与经典问题蓝牙 BLE 扫描面试题大全(1):从基础到实战的深度解析-CSDN博客,但实际面试中,企业更关注候选人对复杂场景的应对能力(如多设备并发扫描、低功耗与高发现率的平衡)和前沿技术的…...
基础测试工具使用经验
背景 vtune,perf, nsight system等基础测试工具,都是用过的,但是没有记录,都逐渐忘了。所以写这篇博客总结记录一下,只要以后发现新的用法,就记得来编辑补充一下 perf 比较基础的用法: 先改这…...
04-初识css
一、css样式引入 1.1.内部样式 <div style"width: 100px;"></div>1.2.外部样式 1.2.1.外部样式1 <style>.aa {width: 100px;} </style> <div class"aa"></div>1.2.2.外部样式2 <!-- rel内表面引入的是style样…...
【Java_EE】Spring MVC
目录 Spring Web MVC 编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 编辑参数重命名 RequestParam 编辑编辑传递集合 RequestParam 传递JSON数据 编辑RequestBody …...
前端开发面试题总结-JavaScript篇(一)
文章目录 JavaScript高频问答一、作用域与闭包1.什么是闭包(Closure)?闭包有什么应用场景和潜在问题?2.解释 JavaScript 的作用域链(Scope Chain) 二、原型与继承3.原型链是什么?如何实现继承&a…...
分布式增量爬虫实现方案
之前我们在讨论的是分布式爬虫如何实现增量爬取。增量爬虫的目标是只爬取新产生或发生变化的页面,避免重复抓取,以节省资源和时间。 在分布式环境下,增量爬虫的实现需要考虑多个爬虫节点之间的协调和去重。 另一种思路:将增量判…...
Redis的发布订阅模式与专业的 MQ(如 Kafka, RabbitMQ)相比,优缺点是什么?适用于哪些场景?
Redis 的发布订阅(Pub/Sub)模式与专业的 MQ(Message Queue)如 Kafka、RabbitMQ 进行比较,核心的权衡点在于:简单与速度 vs. 可靠与功能。 下面我们详细展开对比。 Redis Pub/Sub 的核心特点 它是一个发后…...
