目录

文章目录

前言

一、记忆化搜索

二、题目概略

三、斐波拉契数

四、Function

五、天下第一

六、滑雪

总结


亲爱的读者朋友们,大家好啊!不同的时间,相同的地点,今天又带来了关于搜索部分的讲解。接下来我将接着我前面文章的内容,开始讲解以下记忆化搜索的部分了。

let's go!


前言

前面我们讲解了剪枝的内容,我们接着它,继续剪枝。

记忆化搜索就是我们剪枝的一大部分,我们接下来就学习我们的记忆化搜索吧!


一、记忆化搜索

记忆化搜索也是一种剪枝的策略

通过⼀个"备忘录",记录第⼀次搜索到的结果,当下⼀次搜索到这个状态时,直接在"备忘录"⾥⾯找结果。

我们接下来就看看这部分的题目,在题目中来理解记忆化搜索吧

二、题目概略

509. 斐波那契数 - 力扣(LeetCode)

P1464 Function - 洛谷

P5635 【CSGRound1】天下第一 - 洛谷

P1434 [SHOI2002] 滑雪 - 洛谷

三、斐波拉契数

我们看完题目后,会发现很简单,一个简单的递归就可以解决了,所以我们很快就可以写出这道题:

但是?我们执行时间怎么这么多?

如果卡时间我们不就过不了了吗,所以该怎么办?

我们画一下对应的决策树:

我们发现在递归的过程中,会出现很多重复的展开,我们就需要去将这些重复的内容全部去掉才对。这时候我们记忆化搜索就可以来帮助我们了

我们可以将对应的递归结果存下来,如果再次需要去递归这个数,那么我们判断一下,直接拿对应的值即可

可以看一下它的数据范围是小于等于30,所以我们创建一个35大小的数组即可:

int f[35];//备忘录,存放对应下标i的斐波拉契值

这样,我们就大幅度的降低了我们的时间消耗。记忆化搜索就帮我们剪掉对应的那些重复枝丫

四、Function

首先,先理解一下这个题目:

我们无非就是要设计一个递归函数,从之前的学习后,写一个递归函数难度肯定不大。

但是题目后面又说,如果出现如w(15, 15, 15)的时候会出现很多的调用,这个时候我们就得需要记忆化搜索来记录它的结果,剪掉多余的枝丫。

我们来实现一下最简单的版本:

#include <iostream>
using namespace std;
typedef long long LL;
LL a, b, c;
LL dfs(LL a, LL b, LL c)
{if (a <= 0 || b <= 0 || c <= 0) return 1;if (a > 20 || b > 20 || c > 20) return dfs(20, 20, 20);if (a < b && b < c){return dfs(a, b, c - 1) + dfs(a, b - 1, c - 1) - dfs(a, b - 1, c);}else {return dfs(a - 1, b, c) + dfs(a - 1, b - 1, c) + dfs(a - 1, b, c - 1) - dfs(a - 1, b - 1, c - 1);}
}
int main()
{while(cin >> a >> b >> c){if (a == -1 && b == - 1 && c == -1) break;printf("w(%lld, %lld, %lld) = %lld\n", a, b, c, dfs(a, b, c));}return 0;
}

这是没有记忆化搜索的版本,我们看看能不能通过呢?

会发现全部都超时了,所以我们的记忆化搜索是必须要增加上去的:

由于这里有三个数,我们要通过三个数来映射对应的值,所以我们要使用一个三维数组去映射:

#include <iostream>
using namespace std;
typedef long long LL;
const int N = 25;
LL f[N][N][N]; 
LL a, b, c;
LL dfs(LL a, LL b, LL c)
{if (a <= 0 || b <= 0 || c <= 0) return 1;if (a > 20 || b > 20 || c > 20) return dfs(20, 20, 20);if (f[a][b][c]) return f[a][b][c];//查找备忘录 if (a < b && b < c){return f[a][b][c] = dfs(a, b, c - 1) + dfs(a, b - 1, c - 1) - dfs(a, b - 1, c);}else {return f[a][b][c] = dfs(a - 1, b, c) + dfs(a - 1, b - 1, c) + dfs(a - 1, b, c - 1) - dfs(a - 1, b - 1, c - 1);}
}
int main()
{while(cin >> a >> b >> c){if (a == -1 && b == - 1 && c == -1) break;printf("w(%lld, %lld, %lld) = %lld\n", a, b, c, dfs(a, b, c));}return 0;
}

我们这样就通过了!

可能会有读者问,为什么多组测试数据不清理数组呢?

那是因为我们后面也会用到这个备忘录,并不需要清理

五、天下第一

讲这道题的时候我需要先讲一下取模运算的一些内容

对于取模的加法和乘法的性质:

(a + b + c) % p = (a % p + b % p + c % p) % p

(a * b * c) % p = (a % p * b % p * c % p) % p

在加法和乘法中,括号里面那一坨可以随便加%p,并不会影响结果

那么现在再来理解一下这道题吧:

我们会有一个x和一个y进行不停的执行取模,谁先到0,谁就赢

都不能到0,就平局

题目很简单,只需要通过递归去解决这个相同子问题即可:

还有就是每次x和y都会更新x = (x + y) % p, y = ((x + y) % p + y) % p = (x + y + y) % p

在不停的模中,就会出现重复的情况,我们就需要记录下对应的结果

#include <iostream>
using namespace std;
const int N = 1e4 + 10;
char f[N][N];
int T, p;
char dfs(int x, int y)
{if (f[x][y]) return f[x][y];f[x][y] = '3';if (x == 0) return f[x][y] = '1';else if (y == 0) return f[x][y] = '2';return f[x][y] = dfs((x + y) % p, (x + y + y) % p);
}
int main()
{cin >> T >> p;while(T--){int x, y;cin >> x >> y;char ret = dfs(x, y);if (ret == '1') cout << 1 << endl;else if (ret == '2') cout << 2 << endl;else cout << "error" << endl;}return 0;
}

我们由于有x和y,就采用一个二维数组来映射即可

因为有三种结果,我们就不能直接使用bool数组来标记了,我们可以使用int或者char去记录

但是int没必要,有些浪费空间了,我们直接使用char数组去记录即可。

我们一旦进入函数就要给它先打上平局的'3'才行,如果x或者y成了0,就修改为对应的1或者2

如果没有最后返回的便是平局

六、滑雪

这道题跟前面几道题的难度就不一样了

我们最简单的方法就是枚举i,j

从(i, j)位置向四个方向去走,将最长的路径找出来

dfs(i, j)返回这个点能滑的最远距离

那么怎么让这个往四个方向去走呢,看过前面章节内容的读者就知道这时候我们就需要方向数组:dx[]和dy[]去更新我们的x和y了

我们先将最简单代码来写一下:


#include <iostream>
using namespace std;
const int N = 110;
int a[N][N];
int r, c;
int dx[] = {1, -1, 0, 0};
int dy[] = {0, 0, 1, -1};
int dfs(int i, int j)
{int len = 1;for (int k = 0; k < 4; k++){int x = i + dx[k];int y = j + dy[k];if (x >= 1 && x <= r && y >= 1 && y <= c&& a[x][y] < a[i][j]){len = max(len, dfs(x, y) + 1);}}return len;
}int main()
{cin >> r >> c;for (int i = 1; i <= r; i++){for (int j = 1; j <= c; j++){cin >> a[i][j];}}int ret = 1;for (int i = 1; i <= r; i++){for (int j = 1; j <= c; j++){ret = max(ret, dfs(i, j));}}cout << ret << endl;return 0;
}

我们会发现还是有个例子超时了,我们不加记忆化搜索还是过不了。

由于每次去遍历的时候都会遍历到很多之前走过的节点,我们去遍历的话就会浪费很多时间

我们就得想办法将每个访问过的点记忆下来,这样再访问这个点就可以直接拿到对应的值了。

#include <iostream>
using namespace std;
const int N = 110;
int a[N][N];
int r, c;
int dx[] = {1, -1, 0, 0};
int dy[] = {0, 0, 1, -1};
int f[N][N];
int dfs(int i, int j)
{if(f[i][j]) return f[i][j];int len = 1;for (int k = 0; k < 4; k++){int x = i + dx[k];int y = j + dy[k];if (x >= 1 && x <= r && y >= 1 && y <= c&& a[x][y] < a[i][j]){len = max(len, dfs(x, y) + 1);}}return f[i][j] = len;
}int main()
{cin >> r >> c;for (int i = 1; i <= r; i++){for (int j = 1; j <= c; j++){cin >> a[i][j];}}int ret = 1;for (int i = 1; i <= r; i++){for (int j = 1; j <= c; j++){ret = max(ret, dfs(i, j));}}cout << ret << endl;return 0;
}

我们发现这道题难度不大,只要通过深度搜索我们就可以很简单的将对应的代码写出来。

通过添加映射的备忘录将值记录即可。

但是要注意的是,一定是要出现大量的相同的情况,我们才去使用备忘录,记忆化搜索。

如上这样会访问到很多相同节点一般。

我们就要去使用记忆化搜索剪枝


总结

亲爱的读者朋友们,这篇文章希望大家能够看完前面的文章再来读,这样的话会更加得心应手。

希望大家多多点赞 + 收藏 + 关注!

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

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

相关文章

抗量子加密技术前瞻:后量子时代的密码学革命

目录抗量子加密技术前瞻&#xff1a;后量子时代的密码学革命1. 量子计算威胁现状1.1 量子霸权里程碑1.2 受威胁算法1.3 时间紧迫性2. 抗量子密码学体系2.1 技术路线对比2.2 数学基础革新3. 标准化进程3.1 NIST PQC标准化时间线3.2 当前推荐算法4. 技术实现方案4.1 Kyber密钥交换…

基于STM32设计的矿山环境监测系统(NBIOT)_262

文章目录 一、前言 1.1 项目介绍 【1】开发背景 【2】研究的意义 【3】最终实现需求 【4】项目硬件模块组成 1.2 设计思路 【1】整体设计思路 【2】上位机开发思路 1.3 项目开发背景 【1】选题的意义 【2】摘要 【3】国内外相关研究现状 【5】参考文献 1.4 开发工具的选择 【1】…

电脑如何安装win10专业版_电脑用u盘安装win10专业版教程

电脑如何安装win10专业版&#xff1f;电脑还是建议安装win10专业版。Win分为多个版本&#xff0c;其中家庭版&#xff08;Home&#xff09;和专业版&#xff08;Pro&#xff09;是用户选择最多的两个版本。win10专业版在功能以及安全性方面有着明显的优势&#xff0c;所以电脑还…

多语言文本 AI 情感分析 API 数据接口

多语言文本 AI 情感分析 API 数据接口 AI / 文本处理 AI 模型快速分析文本情感倾向 多语言文本 / 情感分析。 1. 产品功能 支持多语言文本情感分析&#xff1b;基于特定 AI 模型&#xff0c;快速识别文本情感倾向&#xff1b;适用于评论分析、舆情监控等场景&#xff1b;全接…

【R语言】R语言的工作空间映像(workspace image,通常是.RData)详解

R语言的工作空间映像&#xff08;.RData&#xff09;详解 在使用 R 语言时&#xff0c;你可能会注意到&#xff0c;每次退出 R 会弹出一个提示&#xff1a; Save workspace image? [y/n/c] 如果你使用的是 Rstudio 这个 IDE 来进行R语言的开发&#xff0c;那么可能弹出的提示…

在线 A2C实践

在线 A2C&#xff08;Actor-Critic&#xff09;算法在推荐系统中的实践&#xff0c;核心是将推荐过程建模为实时交互的强化学习问题&#xff0c;通过 Actor 生成推荐策略、Critic 评估策略价值&#xff0c;实现 “决策 - 反馈 - 更新” 的闭环。从样本设计到最终上线&#xff0…

Eclipse RCP产品动态模块设计

文章目录 遇到问题具体实践效果演示应用下载 遇到问题 如果你是一个To C产品的设计者&#xff0c;势必会遇到用户需求高度分化的场景&#xff0c;随之而来的是繁杂的功能列表&#xff0c;如何让用户只接触与其任务直接相关的功能&#xff0c;隐藏无关元素&#xff1f; 具体实…

NLP自然语言处理: FastText工具与迁移学习基础详解

FastText工具与迁移学习基础详解 一、知识框架总览 FastText工具核心功能与应用场景FastText模型架构与工作原理层次Softmax加速机制哈夫曼树概念与构建方法 二、FastText工具核心解析 2.1 功能定位 双重核心功能 文本分类&#xff1a;可直接用于文本分类任务&#xff0c;快速生…

uni-app 生命周期详解

概述 uni-app 基于 Vue.js 框架开发&#xff0c;其生命周期包含了三个层面&#xff1a; 应用生命周期&#xff1a;App.vue 的生命周期页面生命周期&#xff1a;各个页面的生命周期Vue 组件生命周期&#xff1a;Vue.js 原生的组件生命周期 这三种生命周期在不同场景下会按特定顺…

MCU外设初始化:为什么参数配置必须优先于使能

在微控制器领域&#xff0c;初始化参数配置阶段至关重要。此时&#xff0c;虽无电源驱动&#xff0c;但微控制器在使能信号到来前&#xff0c;借初始化参数配置这一精细步骤&#xff0c;开启关键准备进程。初始化参数配置如同物理坐标锚定、逻辑指令部署、内在秩序预设&#xf…

AI一周事件(2025年8月6日-8月12日)

&#xff08;以下借助 DeepSeek-R1 & ChatGPT-5 辅助整理&#xff09; 一、AI 模型与算法进展 1. OpenAI 正式发布 GPT-5&#xff08;8月7日&#xff09; 事件&#xff1a;OpenAI 于 2025 年 8 月 7 日推出 GPT-5——其自称拥有“PhD 级别”的智能&#xff0c;通过内置…

快速了解自然语言处理

在这个智能时代&#xff0c;我们每天都在和机器 “对话”—— 用语音助手查询天气、让翻译软件跨越语言障碍、靠智能客服解决问题…… 这些便捷体验的背后&#xff0c;都离不开自然语言处理&#xff08;Natural Language Processing&#xff0c;NLP&#xff09; 技术。作为人工…

洛谷 P2607 [ZJOI2008] 骑士-提高+/省选-

题目描述 Z 国的骑士团是一个很有势力的组织&#xff0c;帮会中汇聚了来自各地的精英。他们劫富济贫&#xff0c;惩恶扬善&#xff0c;受到社会各界的赞扬。 最近发生了一件可怕的事情&#xff0c;邪恶的 Y 国发动了一场针对 Z 国的侵略战争。战火绵延五百里&#xff0c;在和平…

不止于GET:掌握POST报错注入的精髓

文章目录引言POST请求简述报错注入核心思想关键前提实战演练POST报错注入与GET报错注入的区别防御之道&#xff1a;如何避免POST报错注入&#xff1f;引言 SQL注入是Web安全领域危害性最大、最常见、最持久的高危漏洞之一。它直接威胁到应用程序核心数据库的安全&#xff0c;可…

01数据结构-Prim算法

01数据结构-Prim算法1.普利姆(Prim)算法1.1Prim算法定义1.2Prim算法逻辑1.3Prim代码分析2.Prim算法代码实现1.普利姆(Prim)算法 1.1Prim算法定义 Prim算法在找最小生成树的时候&#xff0c;将顶点分为两类&#xff0c;一类是在查找的过程中已经包含在生成树中的顶点(假设为A类…

CacheBlend:结合缓存知识融合的快速RAG大语言模型推理服务

温馨提示&#xff1a; 本篇文章已同步至"AI专题精讲" CacheBlend&#xff1a;结合缓存知识融合的快速RAG大语言模型推理服务 摘要 大语言模型&#xff08;LLMs&#xff09;通常在输入中包含多个文本片段&#xff0c;以提供必要的上下文。为了加速对较长LLM输入的预…

Docker 在 Linux 中的额外资源占用分析

Docker 本身作为一个运行时环境&#xff0c;除了容器应用本身消耗的资源外&#xff0c;还会引入一些额外的开销。主要体现在以下几个方面&#xff1a; 1. 存储空间占用 (Disk Space) 这是最显著的额外开销&#xff0c;主要来源于 Docker 的存储驱动&#xff08;如 overlay2&…

[激光原理与应用-264]:理论 - 几何光学 - 什么是焦距,长焦与短焦的比较

长焦与短焦透镜是光学系统中两类核心组件&#xff0c;其成像特性在焦距、视角、景深、像场特性及典型应用中存在显著差异。以下从多个维度进行详细对比&#xff1a;一、核心参数对比参数长焦透镜短焦透镜焦距范围通常 >50mm&#xff08;全画幅相机标准&#xff09;通常 <…

el-input 复制大量数据导致页面卡顿问题解决

问题根源 复制粘贴操作会瞬间触发大量 input 事件&#xff0c;导致 Vue 频繁更新响应式数据&#xff0c;引发性能瓶颈。 解决方案&#xff1a;使用 .lazy 修饰符 <el-input v-model.lazy"inputValue" />

PCIe Electrical Idle Sequences ( EIOS and EIEOS )

前言 PCI Express (PCIe)协议中&#xff0c;EIOS (Electrical Idle Ordered Set) 和 EIEOS (Electrical Idle Exit Ordered Set) 是在高速链路管理和状态切换过程中极为重要的特殊序列。下面做详细解释&#xff1a; 一、EIOS&#xff08;Electrical Idle Ordered Set&#xff0…