精华内容
下载资源
问答
  • 遗传算法是应用于搜寻各类问题最优解的一种方法,因此,基于遗传算法来寻找最大简约树是适合的。但该算法有两个严重的缺点,容易导致过早收敛、以及在进化后期搜索效率低。基于最优原则的最大简约法的启发式搜索,将...
  • 在一定的假设下,可把启发式搜索看作一种随机取样的过程。从而把统计推断方法引进搜索。根据上述思想.把Wald序贯概率比检验方法与A(A*)搜索结合,得到一种新算法──SA算法。文中讨论了该算法的优点及...
  • 秃鹰搜索(BES)算法,这是一种新颖的,受自然启发的元启发式优化算法,它模仿秃鹰在寻找鱼类时的狩猎策略或聪明的社交行为。 这是该文件的源代码:Alsattar,HA,Zaidan,AA&Zaidan,BB(2020)。 新颖的元启发式...
  • 电信设备-一种基于启发式方法的信息搜索方法.zip
  • 麻雀搜索算法作为一种启发式算法,模仿了掠夺性活动和麻雀群的逃逸活动,具有更好的收敛性能比其他一些群智能算法要好。
  • 使用java语言写的八数码问题,仅供参考。其中用到了启发式搜索算法
  • 适应距离平衡(FDB):元启发式搜索算法的一种新选择方法
  • 通过对上述问题的研究,给出了最优密钥树结构的定义,并提出一种构建最优密钥树的启发式搜索算法。与传统LKH密钥树结构相比,最优树的不同层具有不同的分支数,因此其可降低密钥更新过程中的处理开销。理论分析与...
  • 常用搜索算法—盲目搜索和启发式搜索

    万次阅读 多人点赞 2019-05-25 00:51:39
    搜索算法 本文主要以一些概念对较为常见的搜索作简单介绍: 一、盲目搜索 ...深度优先搜索算法(简称DFS)是一种用于遍历或搜索树或图的算法。沿着树的深度遍历树的节点,尽可能深的搜索树的分支。当...

    搜索算法

    本文主要以一些概念对较为常见的搜索作简单介绍:

    一、盲目搜索

    对一个图进行搜索意味着按照某种特定的顺序依次访问其顶点。在所有搜索方式中,广度优先算法和深度优先搜索算法都十分重要,因为它们提供了一套系统地访问图数据结构的方法。我们着重讲解广度优先搜索算法。

    1.深度优先搜索
    深度优先搜索算法(简称DFS)是一种用于遍历或搜索树或图的算法。沿着树的深度遍历树的节点,尽可能深的搜索树的分支。当节点的所在边都己被探寻过,搜索将回溯到发现节点的那条边的起始节点。这一过程一直进行到已发现从源节点可达的所有节点为止。由于深度优先搜索不是接下来最短路径算法的基础,因此这里不做拓展。
    2.广度优先搜索
    广度优先搜索算法(简称BFS)又称为宽度优先搜索从起点开始,首先遍历起点周围邻近的点,然后再遍历已经遍历过的点邻近的点,逐步的向外扩散,直到找到终点。
    在执行算法的过程中,每个点需要记录达到该点的前一个点的位置 —父节点。这样做之后,一旦到达终点,便可以从终点开始,反过来顺着父节点的顺序找到起点,由此就构成了一条路径。
    以上两种算法的不同搜索策略可以通过下面网页查看动图,这是两种相邻节点之间的移动代价相等时用到的算法,图中的边不设权值。
    https://cs.stanford.edu/people/abisee/tutorial/bfsdfs.html
    3.Dijkstra算法
    Dijkstra算法是由计算机科学家Edsger W.Dijkstra在1956年提出的。
    考虑这样一种场景,在一些情况下,图形中相邻节点之间的移动代价并不相等。例如,游戏中的一幅图,既有平地也有山脉,那么游戏中的角色在平地和山脉中移动的速度通常是不相等的。在Dijkstra算法中,需要计算每一个节点距离起点的总移动代价。同时,还需要一个优先队列结构。对于所有待遍历的节点,放入优先队列中会按照代价进行排序。在算法运行的过程中,每次都从优先队列中选出代价最小的作为下一个遍历的节点。直到到达终点为止。
    对比了不考虑节点移动代价差异的广度优先搜索与考虑移动代价的Dijkstra算法,又如下动图所示:
    在这里的无法插入图片描述
    可以看出当图形为网格图,并且每个节点之间的移动代价是相等的,那么Dijkstra算法将和广度优先算法变得一样。以下网址链接可以自行设置绿色网格的位置。

    Dijkstra算法(可自行设置障碍物)

    二、启发式搜索算法

    1.贪婪最佳优先
    在Dijkstra算法中,我已经发现了其最终要的缺陷,搜索存在盲目性。在这里,我们只针对这个痛点,采用贪婪最佳优先搜索来解决。如何解决?我们只需稍微改变下观念即可,在Dijkstra算法中,优先队列采用的是,每个顶点到起始顶点的预估值来进行排序。在贪婪最佳优先搜索采用的是,每个顶点到目标顶点的预估值来进行排序。
    两者的搜索过程对比如下动图所示:
    在这里插入图片描述
    明显看到右边的算法(贪婪最佳优先搜索 )寻找速度要快于左侧,虽然它的路径不是最优和最短的,但障碍物最少的时候,他的速度却足够的快。这就是贪心算法的优势,基于目标去搜索,而不是完全搜索。
    贪婪最佳优先搜索动态图(可自行设置障碍物)

    2.A star算法
    我们找到了最短路径和搜索顶点最少数量的两种方案,Dijkstra 算法和贪婪最佳优先搜索。接下来能否汲取两者的有点选择既速度快又能得到最优解的算法?.
    A star算法正是这么做了,它吸取了Dijkstra 算法中的当前代价,为每个边长设置权值,不停的计算每个顶点到起始顶点的距离,以获得最短路线,同时也汲取贪婪最佳优先搜索算法中不断向目标前进优势,并持续计算每个顶点到目标顶点的距离,以引导搜索队列不断想目标逼近,从而搜索更少的顶点,保持寻路的最优解。A star算法在运算过程中,每次从优先队列中选取f(n)值最小(优先级最高)的节点作为下一个待遍历的节点。A star算法使用两个集合来表示待遍历的节点,与已经遍历过的节点,这通常称之为open_set和close_set。
    A star算法优先队列排序方式基于估价值,估价值由顶点到起始顶点的距离(代价)加上顶点到目标顶点的距离(启发函数)之和构成。
    A star算法、贪婪最佳优先、Dijkstra算法三者的静态效果图如下:
    在这里插入图片描述
    三者动态效果图对比(可自行设置障碍物)

    三、启发函数

    f ( n ) = g ( n ) + h ( n ) f(n)=g(n)+h(n) f(n)=g(n)+h(n)
    f(n)是节点n的综合优先级。当我们选择下一个要遍历的节点时,我们总会选取综合优先级最高(值最小)的节点。g(n) 是节点n距离起点的代价。h(n)是节点n距离终点的预计代价,这也就是A star算法的启发函数。
    上面已经提到,启发函数会影响A star算法的行为。
    在极端情况下,当启发函数h(n)始终为0,则将由g(n)决定节点的优先级,此时算法就退化成了Dijkstra算法。
    如果h(n)始终小于等于节点n到终点的代价,则A star算法保证一定能够找到最短路径。但是当h(n)的值越小,算法将遍历越多的节点,也就导致算法越慢。
    如果h(n)完全等于节点n到终点的代价,则A star算法将找到最佳路径,并且速度很快。可惜的是,并非所有场景下都能做到这一点。因为在没有达到终点之前,我们很难确切算出距离终点还有多远。
    如果h(n)的值比节点n到终点的代价要大,则A star算法不能保证找到最短路径,不过此时会很快。在另外一个极端情况下,如果h(n)相较于g(n)大很多,则此时只有h(n)产生效果,这也就变成了贪婪最佳优先搜索。
    由上面这些信息我们可以知道,通过调节启发函数我们可以控制算法的速度和精确度。因为在一些情况,我们可能未必需要最短路径,而是希望能够尽快找到一个路径即可。这也是A star算法比较灵活的地方。对于网格形式的图,有以下这些启发函数可以使用:
    如果图形中只允许朝上下左右四个方向移动,则可以使用曼哈顿距离。
    如果图形中允许朝八个方向移动,则可以使用对角距离。
    如果图形中允许朝任何方向移动,则可以使用欧几里得距离。

    总结

    以下网页是五种不同搜索算法的搜索过程对比:

    五种搜索算法(可进行添加多种障碍物)

    下面对在有权图(紫)和无权图(黄)上利用搜索算法的特点做一个总结:

    本文相关PDF文件:
    Graph Search Algorithms

    本文参考文章链接:

    http://frankorz.com/2017/12/16/greedy-best-find-search/
    https://cs.stanford.edu/people/abisee/tutorial/customize.html
    https://zhuanlan.zhihu.com/p/54510444?utm_source=com.tencent.tim&utm_medium=social&utm_oi=774664375033163776
    https://www.gameres.com/777251.html

    展开全文
  • 算法之启发式搜索

    2020-10-29 18:59:26
    启发式搜索从名字上来讲,我们就可以知道启发式搜索一种有目的性的搜索,是和盲目搜索(深度优先搜索和广度优先搜索)有着重要的区别。

    启发式搜索从名字上来讲,我们就可以知道启发式搜索是一种有目的性的搜索,是和盲目搜索(深度优先搜索和广度优先搜索)有着重要的区别。
    尚未更新,请原谅。

    展开全文
  • 提出了一种基于启发式搜索的主动定位算法.首先利用自适应粒子聚类算法对粒子进行聚类;然后分别构造路径规划树和解空间树,并根据优先级评估函数计算解空间树中所有节点的优先级,利用优先队列式分支限界法解决路径搜索...
  • 个寻星算法,1个文件,无附加功能。... 启发式权重可以更改为更贪婪或设置为 0 以获得 Dijkstra 算法。 蓝色绘制的节点是开放集的部分。 绿色绘制的节点是闭集的部分。 红色绘制的节点显示最终路径。
  • 前言 魔兽世界、仙剑奇侠传这类 MMRPG(Multiplayer Online Role-PlayingGame) 游戏中,有个非常重要的功能,那就是人物角色...实际上,这是个非常典型的路径搜索问题。人物的起点就是他当下所在的位置,终点就...

    前言

    魔兽世界、仙剑奇侠传这类 MMRPG(Multiplayer Online Role-PlayingGame) 游戏中,有一个非常重要的功能,那就是人物角色的自动寻路。当人物处于游戏地图中的某个位置的时候,我们用鼠标点击另外一个相对较远的位置,人物就会自动地绕过障碍物走过去。这个功能是怎么实现的呢?

    路径搜索问题

    实际上,这是一个非常典型的路径搜索问题。人物的起点就是他当下所在的位置,终点就是鼠标点击的位置。我们需要在地图中,找一条从起点到终点的路径。这条路径要绕过地图中所有障碍物,并且走的路不能太绕。

    理论上讲,最短路径显然是最聪明的走法,是这个问题的最优解。不过,在之前最优出行路线规划的问题中,我们也讲过,如果为了计算两点之间的最短路径,在一个超级大图上动用 Dijkstra 算法,遍历所有的顶点和边,显然会非常耗时。在真实的软件开发中,我们所面对的是超级大的地图和海量的寻路请求,如果算法的执行效率太低,这显然是无法接受的。

    其实,像出行路线规划、游戏寻路等这些真实软件开发中的问题,一般情况下,我们都不需要非得求出最优解(也就是最短路径)。在权衡路线规划质量和执行效率的情况下,我们只需要寻求一个次优解就足够了。那么,如何快速找出一条接近于最短路线的次优路线呢?这就要用到 A* 算法了。

    启发式搜索算法

    在介绍A* 算法之前,先介绍一下启发式搜索算法。不过在说它之前,我们还要先了解一下状态空间搜索

    状态空间搜索,就是将一个问题的求解过程表现为从初始状态到目标状态寻找一条路径的过程。通俗点说,就是要在两点之间求一条线路,这两点是问题的开始和问题的结果,而这一线路不一定是直线,可以是曲折的。由于求解问题的过程中分支有很多(即求解方式有很多种),到达目标状态的方式也就有很多,这主要是由于求解过程中求解条件的不确定性和不完备性造成的。求解的路径很多,这就构成了一个图,我们说这个图就是状态空间。问题的求解实际上就是在这个图中找到一条路径可以从问题的开始到问题的结果。这个寻找的过程就是状态空间搜索。

    常用的状态空间搜索有广度优先搜索和深度优先搜索,但是它们存在着一个很大的缺陷,就是它们都是在一个给定的状态空间中穷举,都是根据搜索的顺序依次进行搜索,称为盲目搜索,在状态空间不大的时候可以用,但是如果状态空间非常大并且不可预测的情况下就不可取了,它们的效率会非常低。这时就需要用到启发式搜索

    启发式搜索算法,就是在状态空间中先对每一条搜索分支进行评估,得到最好的分支,再从这个分支继续搜索从而到达目标,这样可以有效省略大量无谓的搜索路径,大大提高了搜索效率。在启发式搜索中,对分支的评估是非常重要的,启发式搜索算法定义了一个估价函数 f(x),与问题相关的启发式信息都被计算为一定的 f(x) 值,引入到搜索过程中。f(x) = g(x) + h(x),其中 f(x) 是节点 x的估价函数,g(x)是在状态空间中从初始节点到节点 x的实际代价,h(x)是从节点 x到目标节点的最佳路径的估计代价。g(x)是已知的,所以在这里主要是 h(x) 体现了搜索的启发信息,h(x)专业的叫法是启发函数。换句话说,g(x)代表了搜索的广度的优先趋势。但是当 h(x) >> g(x)时,可以忽略g(x),从而提高效率。

    A* 算法

    A* 算法正是利用启发式搜索策略来选择最优的扩展节点,从而提升效率的。实际上,A* 算法就是在 Dijkstra 算法的基础上进行优化和改造。

    回顾一下 Dijkstra 算法的实现思路,其实有点儿类似广度优先搜索(BFS)算法,它每次找到跟起点最近的顶点,然后往外扩展。这种往外扩展的思路,其实有些盲目。为什么这么说呢?举一个例子,下面这个图对应一个真实的地图,每个顶点在地图中的位置,我们用一个二维坐标(x,y)来表示,其中,x 表示横坐标,y 表示纵坐标。每条边表示一条路,边上的权值代表路径的长度。
    在这里插入图片描述
    在 Dijkstra 算法的实现思路中,我们用一个优先级队列,来记录已经遍历到的顶点以及这个顶点与起点之间的路径长度。顶点与起点间的路径长度越小,越先被从优先级队列中取出来扩展,从图中举的例子可以看出,尽管我们期望找的是从起点 s 到终点 t 的路线,但是最先被搜索到的顶点依次是 1,2,3。这个搜索方向跟我们期望的路线方向是反着的,路线搜索的方向明显“跑偏”了。之所以会“跑偏”,那是因为我们是按照顶点与起点的路径长度的大小,来安排出队列顺序的。与起点越近的顶点,就会越早出队列。我们并没有考虑到这个顶点到终点的距离,所以,在地图中,尽管 1,2,3 三个顶点离起始顶点最近,但离终点却越来越远。

    如果我们综合更多的因素,把这个顶点到终点可能还要走多远,也考虑进去,综合来判断哪个顶点该先出队列,那是不是就可以避免“跑偏”呢?

    当我们遍历到某个顶点的时候,从起点走到这个顶点的路径长度是确定的,我们记作 g(i)(i 表示顶点编号)。但是,从这个顶点到终点的路径长度是未知的。虽然确切的值无法提前知道,但是我们可以用其他估计值来代替。这里我们可以通过这个顶点跟终点之间的直线距离,也就是欧几里得距离,来近似地估计这个顶点跟终点之间的路径长度注意:路径长度跟直线距离是两个概念)。我们把这个距离记作 h(i)(i 表示这个顶点的编号),h(i) 专业的叫法是启发函数(heuristic function)。
    由于欧几里得距离的计算公式,会涉及比较耗时的开根号计算,所以,我们一般通过另外一个更加简单的距离计算公式,那就是曼哈顿距离(Manhattan distance)。曼哈顿距离是两点之间横纵坐标的距离之和。计算的过程只涉及加减法、符号位反转,所以比欧几里得距离更加高效。

    int hManhattan(Vertex v1, Vertex v2) { // Vertex表示顶点
      return Math.abs(v1.x - v2.x) + Math.abs(v1.y - v2.y);
    }
    

    原来在 Dijkstra 算法中,只是单纯地通过顶点 i 与起点之间的路径长度 g(i),来判断谁先出队列,现在有了这个顶点到终点的路径长度估计值,我们可以通过两者之和 f(i)=g(i)+h(i),来判断哪个顶点该最先出队列。综合两部分,我们就能有效避免刚刚讲的“跑偏”。这里 f(i) 的专业叫法是估价函数(evaluation function)。

    从刚刚的描述,我们可以发现,A 算法实际上就只是对 Dijkstra 算法的简单改造*。实际上,代码实现方面,我们也只需要稍微改动几行代码,就能把 Dijkstra 算法的代码实现,改成 A* 算法的代码实现。将整个地图抽象成一个有向有权图的代码实现如下:

    public class Graph { // 有向有权图的邻接表存储方法
      private LinkedList<Edge> adj[]; // 邻接表
      private int v; // 顶点个数
    
      public Graph(int v) {
        this.v = v;
        this.adj = new LinkedList[v];
        for (int i = 0; i < v; ++i) {
          this.adj[i] = new LinkedList<>();
        }
      }
    
      public void addEdge(int s, int t, int w) { // 添加一条边
        this.adj[s].add(new Edge(s, t, w));
      }
    
      private class Edge {
        public int sid; // 边的起始顶点编号
        public int tid; // 边的终止顶点编号
        public int w; // 权重
        public Edge(int sid, int tid, int w) {
          this.sid = sid;
          this.tid = tid;
          this.w = w;
        }
      }
      
      // 下面这个类是为了A* 算法实现中,顶点的定义
      private class Vertex { //顶点的定义
      	public int id; // 顶点编号ID
      	public int dist; // 从起始顶点到这个顶点的距离,也就是g(i)
      	public int f; // 估价函数 f(i)=g(i)+h(i)
      	public int x, y; // 顶点在地图中的坐标(x, y)
      	public Vertex(int id, int x, int y) {
        	this.id = id;
       		this.x = x;
        	this.y = y;
        	this.f = Integer.MAX_VALUE;
        	this.dist = Integer.MAX_VALUE;
      	}
      }
      
      // Graph类的成员变量,在构造函数中初始化
      Vertex[] vertexes = new Vertex[this.v];
      // 新增一个方法,添加顶点的横纵坐标
      public void addVetex(int id, int x, int y) {
      	vertexes[id] = new Vertex(id, x, y)
      }
    }
    

    在 A* 算法的代码实现中,图 Graph 类的定义跟 Dijkstra 算法中的定义一样。而顶点 Vertex 类的定义,跟 Dijkstra 算法中的定义,稍微有点儿区别,多了 x,y 坐标,以及刚刚提到的 f(i) 值。而 A* 算法代码实现的主要逻辑是下面这段代码。它跟 Dijkstra 算法的代码实现,主要有 3 点区别:

    • 优先级队列构建的方式不同。A* 算法是根据 f(i) 值(f(i)=g(i)+h(i))来构建优先级队列,而 Dijkstra算法是根据 dist 值(也就是刚刚讲到的 g(i))来构建优先级队列;
    • A* 算法在更新顶点 dist 值的时候,会同步更新 f(i) 值;
    • 循环结束的条件也不一样。Dijkstra 算法是在终点出队列的时候才结束,A* 算法是一旦遍历到终点就结束。
    private class PriorityQueue { // 根据vertex的f值构建小顶堆,而不是按照dist
      private Vertex[] nodes;
      private int count;
      public PriorityQueue(int v) {
        this.nodes = new Vertex[v+1];
        this.count = v;
      }
      public Vertex poll() 
      public void add(Vertex vertex) 
      // 更新结点的值,并且从下往上堆化,重新符合堆的定义。时间复杂度O(logn)。
      public void update(Vertex vertex) 
      public boolean isEmpty() 
    }
    
    public void astar(int s, int t) { // 从顶点s到顶点t的路径
      int[] predecessor = new int[this.v]; // predecessor 数组记录每个顶点的前驱顶点,用来还原最短路径
      PriorityQueue queue = new PriorityQueue(this.v); // 根据vertex的f值构建小顶堆
      boolean[] inqueue = new boolean[this.v]; // 标记是否进入过队列
      vertexes[s].dist = 0; // 把起始顶点 s 的 dist 值初始化为 0
      vertexes[s].f = 0; // 把起始顶点 s 的 f 值初始化为 0
      queue.add(vertexes[s]); // 将起始顶点 s 添加到优先级队列中
      inqueue[s] = true;
      while (!queue.isEmpty()) {
        Vertex minVertex = queue.poll(); // 取堆顶元素并删除
        for (int i = 0; i < adj[minVertex.id].size(); ++i) {
          Edge e = adj[minVertex.id].get(i); // 取出一条与minVetex相连的边 e
          Vertex nextVertex = vertexes[e.tid]; // 边 e指向的顶点为nextVertex,即取出的有向边为:minVertex-->nextVertex
          if (minVertex.dist + e.w < nextVertex.dist) { // 若存在更短的路径,更新nextVertex的dist,f
            nextVertex.dist = minVertex.dist + e.w; // 更新顶点 dist值
            nextVertex.f = nextVertex.dist + hManhattan(nextVertex, vertexes[t]); // 同步更新 f值
            predecessor[nextVertex.id] = minVertex.id;
            if (inqueue[nextVertex.id] == true) { // 如果这个顶点已经在优先级队列中了,就不要再将它重复添加进去,直接更新队列中该顶点的dist值即可
              queue.update(nextVertex);
            } else {
              queue.add(nextVertex);
              inqueue[nextVertex.id] = true; // 每当有新的顶点进入队列后,要在 inqueue数组中标记
            }
          }
          if (nextVertex.id == t) { // 一旦遍历到终点 t就可以结束while了
            queue.clear(); // 只有清空queue,才能推出while循环
            break; // 这里的break 只能退出for循环
          }
        }
      }
      // 输出路径
      System.out.print(s);
      print(s, t, predecessor); 
    }
    
    private void print(int s, int t, int[] predecessor) { // 通过递归的方式,将路径打印出来
      if (s == t) return;
      print(s, predecessor[t], predecessor);
      System.out.print("->" + t);
    }
    

    尽管 A* 算法可以更加快速的找到从起点到终点的路线,但是它并不能像 Dijkstra 算法那样,找到最短路线。这是为什么呢?

    要找出起点 s 到终点 t 的最短路径,最简单的方法是,通过回溯穷举所有从 s 到达 t 的不同路径,然后对比找出最短的那个。不过很显然,回溯算法的执行效率非常低,是指数级的。
    在这里插入图片描述
    Dijkstra 算法在此基础之上,利用动态规划的思想,对回溯搜索进行了剪枝,只保留起点到某个顶点的最短路径,继续往外扩展搜索。动态规划相较于回溯的穷举搜索,只是换了一个实现思路,但它实际上也考察到了所有从起点到终点的路线,所以才能得到最优解。
    在这里插入图片描述
    而 A* 算法之所以不能像 Dijkstra 算法那样,找到最短路径,主要原因是两者的 while 循环结束条件不一样。刚刚我们讲过,Dijkstra 算法是在终点出队列的时候才结束循环,A* 算法是一旦遍历到终点就结束循环。对于 Dijkstra 算法来说,当终点出队列的时候,终点的 dist 值是优先级队列中所有顶点的最小值,即便再运行下去,终点的 dist 值也不会再被更新了。对于 A* 算法来说,一旦遍历到终点,我们就结束 while 循环,这个时候,终点的 dist 值未必是所有顶点中的最小值。换句话说,A* 算法是利用贪心算法的思路,每次都找 f 值最小的顶点出队列,一旦搜索到终点就清空优先队列,退出while循环,不再继续考察其他顶点和路线了。所以,它并没有考察所有的路线,也就不可能找出最短路径了。

    解答开篇:如何用A*搜索算法实现游戏中的寻路功能?

    要利用 A* 算法解决这个问题,我们只需要把地图抽象成图就可以了。不过,游戏中的地图跟我们平常用的地图软件中的地图是不一样的。因为游戏中的地图并不像我们现实生活中那样,存在规划非常清晰的道路,更多的是宽阔的荒野、草坪等。所以,我们也就没法利用之前讲到的抽象方法,把地图上的岔路口抽象成顶点,把岔路口与岔路口之间的路抽象成边。

    实际上,我们可以换一种抽象的思路,把整个地图分割成一个一个的小方块。在某一个方块上的人物,只能往上下左右四个方向的方块移动。我们可以把每个方块抽象成一个顶点,在两个相邻的方块之间连接两条有向边,并且边的权值都是 1。所以,这个问题就转化成,在一个有向有权图中,找某个顶点到另一个顶点的路径问题。将游戏地图抽象成边权值为 1 的有向图之后,我们就可以套用 A* 算法,来实现游戏中人物的自动寻路功能了。

    小结

    一、启发式搜索算法
    1.常用的状态空间搜索有广度优先和深度优先搜索算法,但是它们存在着一个很大的缺陷,就是都是在一个给定的状态空间中穷举,都是根据搜索的顺序依次进行搜索,称为盲目搜索,在状态空间不大的时候可以用,但是如果状态空间非常大并且不可预测的情况下就不可取了,它们的效率会非常低。
    2. 而启发式搜索算法就是在状态空间中先对每一条搜索分支进行评估,得到最好的分支,再从这个分支继续搜索从而到达目标。在启发式搜索中,利用当前与问题有关的信息作为启发式信息指导搜索,这些信息能够有效省略大量无谓的搜索路径,大大提高了搜索效率。
    3. 在启发式搜索中,对分支的评估是非常重要的,如何利用这些启发式信息,启发式搜索算法定义了一个估价函数 f(x),与问题相关的启发式信息都被计算为一定的 f(x) 的值,引入到搜索过程中。f(x) = g(x) + h(x),其中 f(x) 是节点 x的估价函数,g(x)是在状态空间中从初始节点到节点 x的实际代价,h(x)是从节点 x到目标节点的最佳路径的估计代价。g(x)是已知的,所以在这里主要是 h(x) 体现了搜索的启发信息,h(x)专业的叫法是启发函数。换句话说,g(x)代表了搜索的广度的优先趋势。但是当 h(x) >> g(x)时,可以忽略g(x),从而提高效率。
    4. 启发式搜索算法利用估价函数,避免“跑偏”,贪心地朝着最有可能到达终点的方向前进。这种算法找出的路线,并不是最短路线。不过,鉴于启发式搜索算法能很好地平衡路线质量和执行效率,它在实际的软件开发中的应用更加广泛。
    5. 算法实例:A* 算法、IDA* 算法、蚁群算法、遗传算法、模拟退火算法等。

    二、A* 算法
    1.A* 算法就是对 Dijkstra 算法的简单改造。它跟 Dijkstra 算法的代码实现,主要有 3 点区别:
    (1)优先级队列构建的方式不同。A* 算法是根据估价函数 f(i) 的值(f(i)=g(i)+h(i),其中g(i)表示顶点 i 与起点间的路径长度,h(i)表示顶点 i 到终点的路径长度估计值)来构建优先级队列,而 Dijkstra 算法是根据顶点与起点间的路径长度 dist 值(也就是 g(i))来构建优先级队列的;
    (2)A* 算法每次在更新顶点 i 的 dist 值的时候,也会同步更新 f(i) 值;
    (3)循环结束的条件也不一样。Dijkstra 算法是在终点出队列的时候才结束,A* 算法是一旦遍历到终点就结束。
    2. 尽管 A* 算法可以更加快速的找到从起点到终点的路线,但是它并不能像 Dijkstra 算法那样,找到最短路线。A* 算法实际上是利用贪心算法的思路,每次都找 f 值最小的顶点出队列,一旦搜索到终点就不再继续考察其他顶点和路线了。所以,它并没有考察所有的路线,也就不可能找出最短路径了。
    3. A* 算法应用场景:地图 App 中的出行路线规划问题、游戏中人物角色的自动寻路功能。

    参考

    《数据结构与算法之美》
    王争
    前Google工程师

    展开全文
  • 本文提出了确定性启发式最佳拟合算法(BFA),用于解决NP硬二维矩形填充问题,以最大化矩形片的填充率。 这种新方法有两个阶段:建设阶段和树搜索阶段。 前者旨在通过在评估不同放置位置时采用动作空间和适合度的...
  • MLCS-Astar 是一种快速启发式搜索算法,用于查找多个字符串的最长(或接近最长)公共子序列。 它发表在 2010 年 AAAI 人工智能会议 (AAAI-2010) 上。 有关该算法的详细说明,请阅读以下论文。 Q. Wang、M. Pan、Y....
  • 人工智能蛇游戏 使用的状态空间搜索算法 盲搜 广度优先搜索 ...A* 使用种启发式搜索: 欧几里得距离 出租车距离 原始贪吃蛇游戏代码取自: 我要给它添加人工智能 :winking_face_with_tongue: :thumbs_up:
  • 为了建立个高效的路径搜索引擎,针对大型应用系统中寻径算法的平衡最优性、时间复杂度以及空间复杂度问题,从经典Dijkstra算法出发,将AI领域的决策机制引入到路径搜索中来,提出了启发式最优路径搜索算法。...
  • 研究传感环境下移动对象的反监控问题,给出了三角形网格,穿行代价,搜索相关度等概念,基于A*启发式路径搜索算法,提出了一种传感环境下启发式反监控路径搜索算法。理论分析和实验结果表明,与已有相关研究工作相比...
  • 一种基于变邻域搜索启发式聚类算法.pdf
  • 摘 要:启发式搜索策略概述和有序搜索。启发式搜索弥补盲目搜索的不足,提高搜索效率。一种方法用于排列待扩展节点...利用启发信息的搜索方法叫做启发式搜索方法。关于图搜索的启发式搜索算法就叫做启发式图搜索算法。
  • 研究一种求解圆形和圆形与矩形混合 Packing问题的启发式算法 。借鉴 Agent概念 , 赋予待布物具有跳跃、交换、旋转、移动和容器缩放等 5种搜索行为 ,在寻优过程中以概率机制控制上述各搜索行为 ,并给出寻优过程中启用...
  • 本代码是梵塔难题(汉诺塔问题)四种方法代码(递归、线性算法、启发式、盲目式),都有详细注释,是智能控制课设时所写,基本涵盖所有梵塔难题的matlab代码
  • 启发式搜索解决八数码问题

    热门讨论 2009-05-24 23:34:10
    人工智能 八数码问题 A*算法 智能搜索 用人工智能的A*算法解决八数码的问题
  • 以物料搬运成本最小和非物流关系强度最大来建立生产车间的多目标优化模型,并提出一种启发式算法进行求解。算法采用启发式布局更新策略更新构型,通过结合基于自适应步长梯度法的局部搜索机制和启发式设施变形策略来...
  • 启发式搜索算法概述 随着计算机性能的提高,搜索算法利用计算机的计算资源有目的穷举个问题解空间的部分或所有的可能情况,从而求解出问题的解。现阶段搜索类算法一般有深度/广度优先搜索、枚举算法、A-Star算法...

    在这里插入图片描述
    【由于专栏后几篇限制vip观看,我又把完整算法在公众号“武汉AI算法研习”进行了发布,可以查看全专栏文章。】

    随着计算机性能的提高,搜索算法利用计算机的计算资源有目的穷举一个问题解空间的部分或所有的可能情况,从而求解出问题的解。现阶段搜索类算法一般有深度/广度优先搜索、枚举算法、A-Star算法、蒙特卡洛树搜索等,目前众多的搜索算法都从以下几个方面来降低搜索的时间和复杂性;

    1、搜索前根据条件降低搜索规模

    2、根据问题的约束条件进行剪枝

    3、利用搜索过程中的中间解,避免重复计算

    启发式搜索增量式搜索的区别在于,启发式搜索是利用启发函数来对搜索进行指导,从而实现高效的搜索,启发函数用来估算当前state和目标state之间的距离,启发式搜索是一种“智能”搜索,启发式搜索算法,就是在状态空中的搜索对每一个搜索的位置进行评估,得到最好的位置,再从这个位置进行搜索直到目标,典型的算法例如A_star算法、遗传算法等。增量搜索是对以前的搜索结果信息进行再利用来实现高效搜索,大大减少搜索范围和时间,典型的例如LPA_star、D_star Lite算法等。

    [资料参考]

    1、https://blog.csdn.net/lqzdreamer/article/details/85175372

    2、https://www.jianshu.com/p/c728bb269116

    展开全文
  • 原子轨道搜索(AOS)是一种为优化目的而提出的新型元启发式算法。 该算法的主要概念基于一些量子力学原理和基于量子的原子模型,其中基于电子围绕原子核的一般构型。
  • 要求解决的问题是:以启发式搜索方法求解给定初始状态和目标状态的最优搜索路径。 例如,那么空格应该向上走一步: 问题的解决 解的表示 将九宫格中数字从上到下、从左到右顺序排列后形成个9个数字的序列(空
  • 启发式搜索

    2017-01-31 15:07:34
    启发式搜索一种无信息搜索,一般只适用于求解比较简单的问题,通常是按预定的搜索策略进行搜索,而不会考虑到问题本身的特性(即就是不会利用问题本身的信息)。 常用的非启发式搜索有: 1,广度优先搜索(BFS)...
  • 实验 启发式搜索算法 学号2220103430 班级计科二班 俊峰 实验容 使用启发式搜索算法求解8数码问题 1编制程序实现求解8数码问题算法采用估价函数 其中是搜索树中结点的深度为结点的数据库中错放的棋子个数为结点...
  • 搜索 —— 启发式搜索

    千次阅读 2020-02-03 20:33:21
    启发式搜索算法,就是在状态空间中的搜索对每个搜索的位置进行评估,得到最好的位置,再从这个位置进行搜索直到目标。 有时我们会遇到这样的类题:题目描述的是一道时间复杂度很高的 NP 问题,我们要找到其中的...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 34,154
精华内容 13,661
关键字:

启发式搜索是一种使用搜索方法