0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

一种优化的方法:记忆化搜索

算法与数据结构 来源:小K算法 作者:小K 2022-06-14 10:21 次阅读
01 故事起源有一天小K去滑雪,雪山高低不平,当然小K只能从高的地方向低的地方滑,那如何选择路线才能滑的最远呢? 把这个问题抽象描述如下:

在一个二维地图中,数值代表此处山的高度,在某个点只能滑向上下左右4个相邻的点,最远的滑行路线,也就等价于找出一条最长的数值下降路线。

比如下图中的红色路线就是此时最长的一条路线,长度为10。那要如何找出这样的一条路线呢?
64a37f7a-eb88-11ec-ba43-dac502259ad0.jpg    02 分析在每个点上,只能向周围4个方向滑行,当然前提是此处的高度必须比周围高。 64b7b616-eb88-11ec-ba43-dac502259ad0.jpg  我们当然可以选择尽可能高的位置出发,比如图中17比15要高。 64ff5ffc-eb88-11ec-ba43-dac502259ad0.jpg  但这种有可能会陷入局部最优解,比如从下图中的15开始,最大长度为2。而从13开始会更优,长度为5。 65127cb8-eb88-11ec-ba43-dac502259ad0.jpg  所以启示我们,不能简单的贪心,而是要考虑全局最优,因为每一个起点都有可能是最优的起点。
那就有了初步的框架了,从每一个起点出发,把可行的路线都找出来,也就是能走的路线都走一遍,再比较全局最优的就行了,而且这也正好符合深搜的算法框架。伪代码

			intfind(inti,intj){  //向4个方向尝试  for(i=0->3){  if(ok){  returnfind(next)+1  } } } intmain(){  for(i=0->n){  for(j=0->m) {  t=find(i,j)  ans=max(ans,t)  }  } }
			
									03
									问题上面的做法可以得到最优解,但有一个问题。如下例,以15为起点的时候,会尝试把6->5->4->3->2->1走一遍。但以16为起点的时候,还会尝试把这条路线走一遍,这就会导致大量的重复计算。
			653bb826-eb88-11ec-ba43-dac502259ad0.jpg
			 那能不能优化呢? 之所以重复计算,是因为每一次尝试都是重新的开始,它并不知道这条路已经走过了,也就是没有记忆,所以我们引入一种优化的方法,就是记忆化搜索。
			
									04
									记忆化搜索可以引入一个f[i][j]数组,记录以(i,j)为起点所能找到的最长路线的长度,初始赋值为-1,表示还没有走过。
			6544aac6-eb88-11ec-ba43-dac502259ad0.jpg
			 当走过一点,就将对应的f[i][j]更新为以(i,j)为起点的最大长度。 再回到上面的问题,因为之前肯定走过了(2,3),对应的f[2][3]为6,当尝试从(2,4)出发时,会发现周围已经走过了,只需要更新当前的值+1即可,就避免了重复计算。
			659bca36-eb88-11ec-ba43-dac502259ad0.jpg
			 
									 05
									代码实现路线搜索

			intfind(vector<vector<int>>&snowMountain,vector<vector<int>>&f,inti,intj,intr,intc){ intx,y; if(f[i][j]!=-1) returnf[i][j]; f[i][j]=1; for(intk=0;k< 4;k++){ x=i+direction[k][0]; y=j+direction[k][1]; //validdirection if(x>=0&&x< r && y >=0&&y< c && snowMountain[i][j] >snowMountain[x][y]){ f[i][j]=maxOfTwo(f[i][j],find(snowMountain,f,x,y,r,c)+1); } } returnf[i][j]; }main函数

			intmain(){ ifstreamfin("a.in"); ofstreamfout("a.out"); inti,j,r,c,maxHeight=0; fin>>r>>c; vector<vector<int>>snowMountain(r,vector<int>(c,0)); vector<vector<int>>f(r,vector<int>(c,-1)); for(i=0;i< r; i++)         for(j=0;j< c; j++)             fin >>snowMountain[i][j]; for(i=0;i< r; i++)         for(j=0;j< c; j++) {             maxHeight = maxOfTwo(maxHeight, find(snowMountain, f, i, j, r, c));         }     fout << maxHeight << endl; fin.close(); fout.close(); return0; }
			
									06
									总结记忆化搜索是一种非常实用的算法,因为深搜用递归很容易实现,记忆化又避免了重复子问题的计算,提高了运行效率。 这其实就是动态规划的思想,常见的动态规划用递推实现,相比记忆化搜索实现上会更难一点,而记忆化搜索就没有这个问题。 算法的适用场景也需要根据具体的问题来分析,一般常用在地图或者树型结构中。
			
			审核编辑 :李倩

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 算法
    +关注

    关注

    23

    文章

    4444

    浏览量

    90697
  • 代码
    +关注

    关注

    30

    文章

    4548

    浏览量

    66608

原文标题:啥是记忆化搜索?

文章出处:【微信号:TheAlgorithm,微信公众号:算法与数据结构】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    谷歌搜索引擎优化的各个方面和步骤

    谷歌搜索引擎是最受欢迎和广泛使用的搜索引擎之一,为了使你的网站在谷歌上更好地排名并提高曝光度,你可以采取一些谷歌搜索引擎优化的步骤。 使用关键字研究工具,如Google AdWords
    的头像 发表于 01-25 10:29 270次阅读

    常见的ARM架构分为两一种是M系列另外一种是A系列,这两有什么区别啊?

    现在市面上常见的ARM架构分为两一种是M系列另外一种是A系列,这两有什么区别啊,用的时候他们般分别用在什么地方啊。
    发表于 10-26 07:00

    一种结构道路环境中的视觉导航系统详解

    根据结构道路环境的特点提出了一种将边沿检测和道路环境知识相结合的机器视觉算法 , 并结合基于行为响应的路径规划方法和智能预瞄控制方法 , 实现了
    发表于 09-25 07:23

    MATLAB编程在优化中的应用介绍

    机会。与前几年的高级编程语言相比,这些软件系统非常容易掌握。本书主要试图利用这种三角服务,为设计优化的研究提供一种实用的方法。这本书使用MATLAB@toillustrate并实现各种优化
    发表于 09-21 07:07

    N32903的ADC模块以一种时钟频率初始后,能切换成另外一种时钟频率吗?

    N32903的ADC模块以一种时钟频率初始后,能切换成另外一种时钟频率吗? 最近有个应用:条码打印机。 在检测纸张的类型和尺寸的时候,希望ADC模块工作在500KHz左右;
    发表于 09-01 06:56

    软件优化指南

    抵触。 例如,循环展开是一种可以提高性能的优化技术,但这种优化是以增加代码大小为代价的。 优化的第步是决定要
    发表于 08-28 06:41

    优化Unity程序的方法

    的帧速率,使其成为更好、更流畅的体验。 本指南介绍了优化Unity程序的方法,尤其是它们的GPU使用。 本指南将优化分为三章: •应用程序处理器优化•GPU
    发表于 08-02 18:52

    介绍一种记忆模式下的智能驾驶行车设计方法

    记忆泊车类似,记忆行车这一功能主要实现简单的面向服务的应用服务。实现的典型应用场景包括:上下班路线,接送儿童,商超采购等。
    发表于 07-12 10:07 330次阅读
    介绍<b class='flag-5'>一种</b>纯<b class='flag-5'>记忆</b>模式下的智能驾驶行车设计<b class='flag-5'>方法</b>

    N32903的ADC模块以一种时钟频率初始后,能切换成另外一种时钟频率吗?

    N32903的ADC模块以一种时钟频率初始后,能切换成另外一种时钟频率吗? 最近有个应用:条码打印机。 在检测纸张的类型和尺寸的时候,希望ADC模块工作在500KHz左右;
    发表于 06-13 08:50

    是否有一种方法可以使用Arduino的代码块IDE与ESP MCU起工作?

    你知道是否有一种方法可以使用 Arduino 的代码块 IDE 与 ESP MCU 起工作?Code Blocks 是个非常好的轻量级 IDE,已经适用于几乎所有的 Arduino 开发板。
    发表于 06-09 08:35

    亿级ES数据搜索性能优化

    业务的细分、迭代和时间的推移,这个索引的文档数和搜索的RT开始逐步上升。 下面是这个索引当前的监控情况。 本文介绍社区 利用IndexSorting,将亿级文档搜索性能由最开始2000ms优化到50ms的过程 。如果大家遇到相似
    的头像 发表于 05-26 14:55 506次阅读
    亿级ES数据<b class='flag-5'>搜索</b>性能<b class='flag-5'>优化</b>

    是否有一种简单的方法将esp连接到openhab并发送特殊命令?

    嗨, (首先抱歉我的英语不好) 个月以来我直在玩 ESP,我真的很喜欢它! 但现在我想更进步,将 ESP 连接到 Openhab 并控制灯、RGB-LED 等。 所以我的问题:是否有一种
    发表于 05-24 08:14

    一种简单的报错设计,分享

    一种简单的报错设计,可在次基础上增加。 冲突 阻挡 重复 不在工位 不在岗 计时不准 范围外 强停 其它
    发表于 05-20 20:07

    有没有一种方法可以在“附加板管理器 URL”中指定旧版本?

    总而言之, 我有个在 ESP8266 上使用 painlessMesh 的项目。 已经工作了好几个月了。 不幸的是,最新版本的 8266 内核导致 painlessMesh 编译错误。 有没有一种方法可以在“附加板管理器 URL”中指定旧版本
    发表于 05-08 08:25

    有没有一种方法可以配置个库项目来导出#include 路径、库搜索路径和库名称?

    有没有一种方法可以配置个库项目来导出#include 路径、库搜索路径和库名称,这样只要将它作为依赖项添加到另个项目(lib 或可执行文件)就会自动将该路径和名称添加到依赖项目中?
    发表于 04-19 06:36