算法日记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)技术,允许在不修改内核源码或重启系统的前提下,动态监控内核函数的执行。它是内核调试、性能分析和安全监控的重要工具。以下从技术…...

(二)TensorRT-LLM | 模型导出(v0.20.0rc3)
0. 概述 上一节 对安装和使用有个基本介绍。根据这个 issue 的描述,后续 TensorRT-LLM 团队可能更专注于更新和维护 pytorch backend。但 tensorrt backend 作为先前一直开发的工作,其中包含了大量可以学习的地方。本文主要看看它导出模型的部分&#x…...

CMake基础:构建流程详解
目录 1.CMake构建过程的基本流程 2.CMake构建的具体步骤 2.1.创建构建目录 2.2.使用 CMake 生成构建文件 2.3.编译和构建 2.4.清理构建文件 2.5.重新配置和构建 3.跨平台构建示例 4.工具链与交叉编译 5.CMake构建后的项目结构解析 5.1.CMake构建后的目录结构 5.2.构…...

屋顶变身“发电站” ,中天合创屋面分布式光伏发电项目顺利并网!
5月28日,中天合创屋面分布式光伏发电项目顺利并网发电,该项目位于内蒙古自治区鄂尔多斯市乌审旗,项目利用中天合创聚乙烯、聚丙烯仓库屋面作为场地建设光伏电站,总装机容量为9.96MWp。 项目投运后,每年可节约标煤3670…...
Neo4j 集群管理:原理、技术与最佳实践深度解析
Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...
leetcodeSQL解题:3564. 季节性销售分析
leetcodeSQL解题:3564. 季节性销售分析 题目: 表:sales ---------------------- | Column Name | Type | ---------------------- | sale_id | int | | product_id | int | | sale_date | date | | quantity | int | | price | decimal | -…...

AI,如何重构理解、匹配与决策?
AI 时代,我们如何理解消费? 作者|王彬 封面|Unplash 人们通过信息理解世界。 曾几何时,PC 与移动互联网重塑了人们的购物路径:信息变得唾手可得,商品决策变得高度依赖内容。 但 AI 时代的来…...
使用Matplotlib创建炫酷的3D散点图:数据可视化的新维度
文章目录 基础实现代码代码解析进阶技巧1. 自定义点的大小和颜色2. 添加图例和样式美化3. 真实数据应用示例实用技巧与注意事项完整示例(带样式)应用场景在数据科学和可视化领域,三维图形能为我们提供更丰富的数据洞察。本文将手把手教你如何使用Python的Matplotlib库创建引…...

Linux 内存管理实战精讲:核心原理与面试常考点全解析
Linux 内存管理实战精讲:核心原理与面试常考点全解析 Linux 内核内存管理是系统设计中最复杂但也最核心的模块之一。它不仅支撑着虚拟内存机制、物理内存分配、进程隔离与资源复用,还直接决定系统运行的性能与稳定性。无论你是嵌入式开发者、内核调试工…...

【网络安全】开源系统getshell漏洞挖掘
审计过程: 在入口文件admin/index.php中: 用户可以通过m,c,a等参数控制加载的文件和方法,在app/system/entrance.php中存在重点代码: 当M_TYPE system并且M_MODULE include时,会设置常量PATH_OWN_FILE为PATH_APP.M_T…...
Bean 作用域有哪些?如何答出技术深度?
导语: Spring 面试绕不开 Bean 的作用域问题,这是面试官考察候选人对 Spring 框架理解深度的常见方式。本文将围绕“Spring 中的 Bean 作用域”展开,结合典型面试题及实战场景,帮你厘清重点,打破模板式回答,…...