记忆化搜索——AcWing 901. 滑雪

记忆化搜索

定义

记忆化搜索是一种结合了搜索和动态规划思想的方法。它通过将已经计算过的结果存储起来,在后续遇到相同情况时直接返回存储的结果,避免重复计算。

运用情况

  • 当问题可以用递归方式求解,但存在大量重复计算时。
  • 一些复杂的组合或搜索问题,通过记忆化来提高效率。

注意事项

  • 合理设计存储结构:用于保存已经计算过的状态和结果。
  • 确保正确更新和检索记忆的数据。
  • 注意边界情况和特殊情况的处理,以保证记忆化的准确性。

解题思路

  • 确定问题的递归结构和状态表示。
  • 在递归函数中,先检查当前状态是否已经被记忆,如果是则直接返回记忆的结果。
  • 如果没有记忆,则进行正常的计算,并将结果存储起来。
  • 按照问题的逻辑进行递归调用和结果处理。

记忆化搜索能够有效地减少重复计算,提高算法的效率,在很多情况下是一种非常实用的技术。

AcWing 901. 滑雪   

题目描述

901. 滑雪 - AcWing题库

运行代码

#include <iostream>
#include <vector>
#include <cstring>
using namespace std;
const int R = 300;
const int C = 300;
int r, c;
int grid[R][C];
int dp[R][C];
int dfs(int x, int y) {if (dp[x][y]!= -1) {return dp[x][y];}int maxLen = 1;if (x > 0 && grid[x - 1][y] < grid[x][y]) {maxLen = max(maxLen, 1 + dfs(x - 1, y));}if (x < r - 1 && grid[x + 1][y] < grid[x][y]) {maxLen = max(maxLen, 1 + dfs(x + 1, y));}if (y > 0 && grid[x][y - 1] < grid[x][y]) {maxLen = max(maxLen, 1 + dfs(x, y - 1));}if (y < c - 1 && grid[x][y + 1] < grid[x][y]) {maxLen = max(maxLen, 1 + dfs(x, y + 1));}dp[x][y] = maxLen;return maxLen;
}
int main() {cin >> r >> c;for (int i = 0; i < r; i++) {for (int j = 0; j < c; j++) {cin >> grid[i][j];}}memset(dp, -1, sizeof(dp));int Length = 0;for (int i = 0; i < r; i++) {for (int j = 0; j < c; j++) {Length = max(Length, dfs(i, j));}}cout << Length << endl;return 0;
}

代码思路

  1. 初始化和输入:

    • 定义了常量R和C来表示二维网格的最大行数和列数。
    • 使用cin读取实际的行数r和列数c。
    • 通过双重循环读取每个格子grid[i][j]的值。
  2. 记忆化搜索(DFS + 动态规划):

    • 定义一个dp数组,dp[i][j]表示以grid[i][j]为起点的最长递增路径长度。初始化为-1,表示尚未计算。
    • 实现深度优先搜索(DFS)函数dfs(x, y),它计算以(x, y)为起点的最长递增路径长度。
      • 首先,如果当前位置的最长路径已计算过,则直接返回dp[x][y]。
      • 然后,初始化当前路径长度为1(至少包含当前位置)。
      • 探索四个方向(上、下、左、右),如果相邻格子的值小于当前位置的值,则递归调用dfs,并累加路径长度,取所有可能路径中的最大值。
      • 最后,将计算结果存入dp[x][y]并返回。
  3. 计算并输出最长路径长度:

    • 遍历整个网格,对每个格子调用dfs函数,更新全局变量Length为所有起点的最长路径中的最大值。
    • 输出这个最大长度。

总结:这段代码通过结合深度优先搜索(DFS)和动态规划(记忆化搜索)的方法,有效地解决了在一个二维网格上寻找最长递增路径的问题。记忆化搜索避免了重复计算,提高了算法效率。

改进思路

  1. 剪枝优化:在进行DFS时,可以在判断相邻格子是否符合条件(即值大于当前格子)之前,先检查该格子是否已经被访问过(即dp值是否已经计算过),这样可以减少不必要的递归调用,进一步优化时间复杂度。

  2. 使用迭代法替代递归:对于深度很大的网格,递归可能导致栈溢出。可以考虑使用栈或队列实现广度优先搜索(BFS)或迭代深度优先搜索(迭代DFS),以减少递归调用的深度。

  3. 空间优化:若内存限制严格,可以考虑使用滚动数组或其它空间优化策略来减少dp数组的大小。例如,只需保留上一行或上一列的dp值,因为计算新的一行或列时只需要用到这些信息。

  4. 输入验证:在读取r和c时,可以加入对输入值的校验,确保它们在预设的网格大小范围内,增加程序的健壮性。

  5. 代码注释和可读性:增加详细的注释,尤其是对于算法的核心逻辑部分,以便于他人理解和维护。同时,对变量命名可以更加直观,如将Length改为maxPathLength以提高代码的可读性。

  6. 泛化处理:如果考虑代码的通用性,可以将R和C的常量定义移至函数参数中,使得算法能灵活适应不同大小的网格,提高代码的复用性。

  7. 并行计算:对于大规模的网格,可以探索并行计算的可能性,比如使用OpenMP或其他并行计算框架来加速计算各个起始点的最长路径长度。

改进代码(AI)

#include <iostream>
#include <vector>
#include <cstring>
#include <stack>
using namespace std;const int R = 300;
const int C = 300;
int r, c;
int grid[R][C];
int dp[R][C];
int dx[] = {-1, 1, 0, 0}; // 方向数组,分别对应上、下、左、右
int dy[] = {0, 0, -1, 1};int dfsIterative(int x, int y) {stack<pair<int, int>> stk; // 使用栈模拟深度优先搜索stk.push({x, y});int maxLength = 1;dp[x][y] = 1; // 初始化已访问的格子长度为1while (!stk.empty()) {auto [curX, curY] = stk.top(); stk.pop();for (int dir = 0; dir < 4; ++dir) {int newX = curX + dx[dir];int newY = curY + dy[dir];if (newX >= 0 && newX < r && newY >= 0 && newY < c && grid[newX][newY] > grid[curX][curY] && (dp[newX][newY] == -1 || dp[newX][newY] < dp[curX][curY] + 1)) {dp[newX][newY] = dp[curX][curY] + 1;maxLength = max(maxLength, dp[newX][newY]);stk.push({newX, newY});}}}return maxLength;
}int main() {cin >> r >> c;for (int i = 0; i < r; ++i) {for (int j = 0; j < c; ++j) {cin >> grid[i][j];}}memset(dp, -1, sizeof(dp)); // 初始化dp数组为-1int maxPathLength = 0;for (int i = 0; i < r; ++i) {for (int j = 0; j < c; ++j) {if (dp[i][j] == -1) { // 避免重复计算maxPathLength = max(maxPathLength, dfsIterative(i, j));}}}cout << maxPathLength << endl;return 0;
}

其它代码

#include <iostream>
#include <cstring> 
using namespace std;
const int N = 310;
int n, m;
int h[N][N];
int f[N][N];
int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};
int dfs(int x, int y)
{int &v = f[x][y];if(~v) return v;v = 1;for(int i = 0; i < 4; i++){int a = x + dx[i], b = y + dy[i];if(a >= 1 && a <= n && b >= 1 && b <= m && h[a][b] < h[x][y])v = max(v, dfs(a, b) + 1);}return v;
}
int main()
{cin >> n >> m;for(int i = 1; i <= n; i++)for(int  j = 1; j <= m; j++)cin >> h[i][j];int res = 0;memset(f, -1, sizeof f);for(int i = 1; i <= n; i++)for(int  j = 1; j <= m; j++)res = max(res, dfs(i, j));cout <<res <<endl;return 0;
}

代码思路

  • 定义了一些常量和变量:
    • N 表示最大的行列数。
    • n 和 m 表示实际的行数和列数。
    • h[N][N] 存储矩阵中每个位置的高度值。
    • f[N][N] 用于记忆化已经计算过的最长滑雪长度。
  • dx 和 dy 数组定义了四个方向的移动偏移量。
  • dfs 函数是核心的搜索函数:
    • 通过引用获取 f[x][y],如果已经计算过(不为 -1),则直接返回。
    • 初始化当前位置的最长长度为 1
    • 遍历四个方向,检查新位置是否合法且高度小于当前位置,如果是,则递归调用 dfs 并更新当前位置的最长长度为递归结果加 1 的最大值。
  • 在 main 函数中:
    • 输入矩阵的行数和列数以及每个位置的高度。
    • 初始化 f 数组为 -1
    • 通过两层循环对每个位置调用 dfs 函数,获取最长长度,并不断更新结果 res
    • 最后输出最长长度。

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

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

相关文章

收藏||电商数据采集流程||电商数据采集API接口

商务数据分析的流程 第一步&#xff1a;明确分析目的。首先要明确分析目的&#xff0c;并把分析目的分解成若干个不同的分析要点&#xff0c;然后梳理分析思路&#xff0c;最后搭建分析框架。 第二步&#xff1a;数据采集。主流电商API接口数据采集&#xff0c;一般可以通过数…

顶顶通呼叫中心中间件-私有化asrproxy安装指南

一、安装asrproxy 上传asrproxy安装包到服务器目录&#xff1a;/root 上传完成之后依次执行下面的命令即可依次执行以下命令 cd ~mkdir -p /ddt/asrproxyunzip asrproxy_*.zip -d /ddt/asrproxycd /ddt/asrproxychmod x installlib.sh./installlib.shchmod x asrproxychmod x…

工控巨头去年业绩飙升10%,今年250亿出售子业务给美国黑石集团,意欲何为?...

导语 大家好&#xff0c;我是社长&#xff0c;老K。专注分享智能制造和智能仓储物流等内容。 新书《智能物流系统构成与技术实践》 更多的海量【智能制造】相关资料&#xff0c;请到智能制造online知识星球自行下载。 在工业自动化领域&#xff0c;艾默生一直以其卓越的技术和强…

CubeFS - 新一代云原生存储系统

CubeFS 是一种新一代云原生存储系统,支持 S3、HDFS 和 POSIX 等访问协议,支持多副本与纠删码两种存储引擎,为用户提供多租户、 多 AZ 部署以及跨区域复制等多种特性。 官方文档 CubeFS 作为一个云原生的分布式存储平台,提供了多种访问协议,因此其应用场景也非常广泛,下面…

驱动芯片退饱和保护(DESAT)

短路测试和双脉冲测试。 功率模块的短路承受能力的评估分为短路时间评估和短路能量评估两大类。短路时间由短路检测时间与短路关断时间共同构成 短路检测需要兼顾时效性与抗扰性能&#xff0c;要求系统能够及时响应&#xff0c;避免功率模块损坏。同时能够屏蔽开关过程的干扰…

车辆轨迹预测系列 (一):轨迹预测方法综述解析

文章目录 车辆轨迹预测系列 (一)&#xff1a;轨迹预测方法综述解析1、Contextual FactorsPhysics-related factors (物理相关因素):Road-related factors (道路相关因素):Interaction-related factors (交互相关因素): 2、Output TypesUnimodal Trajectory Prediction(单一模式…

AI音乐大模型:是创意的助力还是产业的挑战?

近期音乐界迎来了一场前所未有的革命。随着多家科技公司纷纷推出音乐大模型&#xff0c;素人生产音乐的门槛被前所未有地拉低&#xff0c;一个崭新的“全民音乐时代”似乎已近在眼前。然而&#xff0c;在这场技术革新的浪潮中&#xff0c;关于AI产品版权归属、创意产业如何在AI…

Python Web实战:Python+Django+MySQL实现基于Web版的增删改查

项目实战 1.创建项目(sms) File->New Project->Django 稍等片刻&#xff0c;项目的目录结构如下图 项目创建后确认是否已安装Django和mysqlclient解释器&#xff0c;如何确认&#xff1f;file->Settings 如果没有请在Terminal终端输入以下命令完成安装 pip instal…

C++初学者指南第一步---5.介绍std::vector

C初学者指南第一步—5.介绍std::vector 目录 C初学者指南第一步---5.介绍std::vector1.初始化/访问2.添加元素3.Resizing调整大小4.在尾部删除元素5. 复制一直是深拷贝&#xff01; 注意std代表C标准库的命名空间&#xff0c;vector&#xff08;向量&#xff09;是标准库中的一…

18V-180V降5V500mA恒压WT5118

18V-180V降5V500mA恒压WT5118 如何实现18V-180V宽电压输入下的恒压5V 500mA输出。输入电压是波动的18V还是高达180V,WT5118都能确保输出端提供稳定的5V电压和500mA的电流。 WT5118 是一款集成了 180V 高电压 MOSFET 的 DC-DC 控制器&#xff0c;专为开关电源设计。该设备具备内…

国产化ETL产品必备的特性(非开源包装)

ETL负责将分布的、异构数据源中的数据如关系数据、平面数据文件等抽取到临时中间层后进行抽取、清洗&#xff08;净化&#xff09;、转换、装载、标准、集成&#xff08;汇总&#xff09;...... 最后加载到数据仓库或数据集市中&#xff0c;成为联机分析处理、数据挖掘的基础。…

代码生成器技术乱弹五十三,人工智能和通用代码生成器的共同点:Token

代码生成器技术乱弹五十三&#xff0c;人工智能和通用代码生成器的共同点&#xff1a;Token 现在&#xff0c;随着人工智能的快速发展&#xff0c;特别是生成式人工智能的爆火&#xff0c;大家逐渐熟悉了一个概念&#xff0c;Token。我称之为字牌。在生成式人工智能的语境下&a…

OpenAI 联合创始人 Ilya Sutskever 的新初创公司致力于“安全超级智能”

OpenAI 前首席科学家伊利亚-苏茨克沃尔&#xff08;Ilya Sutskever&#xff09;在今年 5 月离开了他共同创立的人工智能研究公司后&#xff0c;透露了他的下一个重要项目。 相关阅读&#xff1a;GPT-4o通过整合文本、音频和视觉实现人性化的AI交互&#xff0c;OpenAI推出了其新…

大电流与小电流在检测原理上有区别吗

1 常用电流检测原理 1.1 分流器原理 被测量的电流在输入端电阻上Rshunt形成电压正比于测量电流&#xff0c;通过同相比例电路进行放大输出。 缺点&#xff1a; 输入电流减小时&#xff0c;需要更大的Rshunt&#xff1b;输入电阻Rshunt串入检测回路内将引起被测电流减小&a…

山西青年杂志山西青年杂志社山西青年编辑部2024年第10期目录

本刊专稿 共融共创、校企共建BIM创新创业中心的探索与实践 黄强;马福贵;贾晓敏;苏艳贞;魏艳卿; 1-3 财务管理课程专创融合教学改革与实践 宋衍程; 4-7 数字化赋能国际贸易实务课程建设研究 吴珍彩; 8-11《山西青年》投稿&#xff1a;cn7kantougao163.com 青年教育研…

GD32F303 低功耗模式要点

我们都知道&#xff0c;MCU有低功耗模式&#xff0c;比如GD32F303芯片&#xff0c;就有Sleep、Deepsleep和Standby三种模式。关于这三种模式的具体使用方法&#xff0c;小伙伴们可以参考《GD32F30x系列用户手册》。 今天我们来聊下几个低功耗模式要点。 1、进入低功耗模式后I…

perfect-scrollbar缩小浏览器窗口滚动条无线滚动的bug

https://github.com/mdbootstrap/perfect-scrollbar/issues/153

Sa-token基本使用教程(全网最详细!!!)

1.概述 1.1 Sa-Token介绍 功能简单示例 1.2 Sa-Token 功能一览 2. 使用 2.1 导入依赖 2.2 springBoot的简单集成 2.2.1 配置文件 2.2.2 controller 2.2.3 简单登录页面 2.3 功能详解 2.3.1 登录认证 2.3.1.1 登录与注销 NotLoginException 登录分析 先校验账号和…

Python3,10行代码,从数据库获取各个维度的数据统计,并把结果输出在Excel中。

10行代码自动统计数据 1、引言2、代码实例3、总结 1、引言 小屌丝&#xff1a;鱼哥帮个忙 小鱼&#xff1a;稍等会哦&#xff0c; 小屌丝&#xff1a;好嘞。 小屌丝&#xff1a; 鱼哥&#xff0c; 还没忙完嘛&#xff1f; 小鱼&#xff1a;快了快了&#xff0c; 再耐心等一等…

Springboot拓展之整合邮件 JavaMail的使用与实操

邮件 电子邮件仍然是我们企业间交往的一种非常常见的方式 发送简单邮件 第一步首先导入坐标 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-mail</artifactId><version>2.6.13</version&…