码迷,mamicode.com
首页 > 编程语言 > 详细

A* search算法

时间:2017-10-08 00:55:48      阅读:279      评论:0      收藏:0      [点我收藏+]

标签:需要   程序   引入   art   sea   核心   返回   alt   current   

今天,还是国庆和中秋双节的时间节点,一个天气不错的日子,孩子已经早早的睡觉了,玩了一整天,也不睡觉,累的实在扛不住了,勉强洗澡结束,倒床即睡着的节奏。。。

 

不多说题外话,进入正题。

 

什么是A*搜索算法呢?就用百科的解说吧:

A*算法,A*(A-Star)算法是一种静态路网中求解最短路径最有效的直接搜索方法,也是解决许多搜索问题的有效算法。算法中的距离估算值与实际值越接近,最终搜索速度越快。

 

A*搜索的实际应用场景很多,但是大家最为熟悉的恐怕莫过于游戏了。典型的游戏就是穿越障碍寻宝,要求在最少的代价内找到宝贝,通常游戏中的代价,就是用最少的步骤实现宝贝的找寻。还有一种游戏场景是,给定入口地点,用最少的步骤走到指定的出口地点,中间有障碍物,每次只能在上下左右四个方向上走一步,且不能穿越障碍物。

 

就拿第二种游戏场景来解释A* search具体指的是什么内容吧。

技术分享

如上图所示,假设我们有一个7*5的迷宫方格,绿色的点表示起点,红色的点表示终点。中间三个蓝色的格子表示一堵墙,是障碍物。游戏的规则,是绿色的起点,每次只能向上下左右4个方向中移动一步,且不能穿越中间的墙,以最少的步骤到达红色的终点

 

在解决这个问题之前,先要引入A*搜索算法的核心集合和公式:

核心集合:OpenList,CloseList

核心公式:F=G+H

其中,OpenList和CloseList用来存储格子点信息,OpenList表示可到达格子节点集合,CloseList表示已到达格子节点集合。

F=G+H表示对格子价值的评估,G表示从起点到当前点的代价;H表示从当前点到达终点的代价,指不考虑障碍物遮挡的情况下,这里,代价是指走的步数。至于F,就是对G和H的综合评估了,当然F越小,则从起点到达终点付出的代价就越小了。

 

就实际操作一下吧。还是上面的图,每个节点,用n(x,y)表示,x表示横坐标,y表示纵坐标,比如绿色的起点是n(1,2):

技术分享

第一步:把起点放入OpenList里面。

OpenList: n(1,2)

CloseList

 

第二步:找出OpenList中F值最小的方格,即唯一的方格n(1,2)作为当前方格,并把当前格移出OpenList,放入CloseList。表示这个格子已到达且验证过了。

OpenList

CloseList:n(1,2)

 

第三步:找出当前格上下左右所有可到达的格子,看它们是否在OpenList当中。如果不在,加入OpenList,计算出相应的G、H、F值,并把当前格子作为它们的“父节点”。

技术分享

OpenList:n(0,2), n(1,1), n(2,2), n(1,3)

CloseList:n(1,2) 

其中,n(0,2), n(1,1), n(2,2), n(1,3)的父节点是n(1,2).所谓的父节点,表示当前的这几个节点n(0,2), n(1,1), n(2,2), n(1,3)都是从这个所谓的父节点出发得到的分支节点,父节点用作后续找出最短路径用的

 

上述3步,是一次局部寻路的过程,我们需要不断的重复第二步第三步,最终找到到达终点的最短路径。

第二轮 ~ 第一步:找出OpenList中F值最小的方格,即方格n(2,2)作为当前方格,并把当前格移出OpenList,放入CloseList。代表这个格子已到达并检查过了。

技术分享

此时的两个核心集合的节点信息:

OpenList:n(0,2), n(1,1), n(1,3)

CloseList:n(1,2), n(2,2)

其中,n(0,2), n(1,1), n(1,3)的父节点是n(1,2),n(2,2)的上一级节点(也可以称为父节点)是n(1,2).

 

第二轮 ~ 第二步:找出当前格上下左右所有可到达的格子,看它们是否在OpenList当中。如果不在,加入OpenList,计算出相应的G、H、F值,并把当前格子作为它们的“父节点”。

技术分享

此时的两个核心集合的节点信息:

OpenList:n(0,2), n(1,1), n(1,3);n(2,1), n(2,3)

CloseList:n(1,2) <-----n(2,2)

其中,n(0,2), n(1,1), n(1,3)的父节点是n(1,2),而n(2,1), n(2,3)的父节点是n(2,2). CloseList中节点的指向关系,反映了寻路的路径过程。

为什么这一次OpenList只增加了两个新格子呢?因为n(3,2)是墙壁,自然不用考虑,而n(1,2)在CloseList当中,说明已经检查过了,也不用考虑

 

第三轮 ~ 第一步:找出OpenList中F值最小的方格。由于这时候多个方格的F值相等,任意选择一个即可,比如n(2,3)作为当前方格,并把当前格移出OpenList,放入CloseList。代表这个格子已到达并检查过了 

技术分享

此时的两个核心集合的节点信息:

OpenList:n(0,2), n(1,1), n(1,3);n(2,1) 

CloseList:n(1,2) <-----n(2,2)<-----n(2,3)

其中,n(0,2), n(1,1), n(1,3)的父节点是n(1,2),而n(2,1)的父节点是n(2,2)。CloseList中节点的指向关系,反映了寻路的路径过程。

 

第三轮 ~ 第二步:找出当前格上下左右所有可到达的格子,看它们是否在OpenList当中。如果不在,加入OpenList,计算出相应的G、H、F值,并把当前格子作为它们的“父节点”。

技术分享

此时的两个核心集合的节点信息:

OpenList:n(0,2), n(1,1), n(1,3);n(2,1) ;n(2,4)

CloseList:n(1,2) <-----n(2,2)<-----n(2,3)

其中,n(0,2), n(1,1), n(1,3)的父节点是n(1,2),而n(2,1)的父节点是n(2,2)。n(2,4)的父节点是n(2,3). CloseList中节点的指向关系,反映了寻路的路径过程。

 

剩下的就是以前面的方式继续迭代,直到OpenList中出现终点方格为止。

 

实际的推理,就到这里,下面,将结合上述的推理理论,用java程序,加以实现。今天,先将伪代码附上,改天将具体的java实现代码贴上来。

public Node AStarSearch(Node start, Node end) {
    // 把起点加入openList  
    openList.add(start);
    //主循环,每一轮检查一个当前方格节点
    while (openList.size() > 0) {
        // 在OpenList中查找F值最小的节点作为当前方格节点
        Node current = findMinNode();
        // 当前方格节点从open list中移除
        openList.remove(current);
        // 当前方格节点进入closeList
        closeList.add(current);
        // 找到所有邻近节点
        List<Node> neighbors = findNeighbors(current);
        for (Node node : neighbors) {
            if (!openList.contains(node)) {
                //邻近节点不在openList中,标记父亲、G、H、F,并放入openList
                markAndInvolve(current, end, node);
            }
        }
        //如果终点在OpenList中,直接返回终点格子
        if (find(openList, end) != null) {
            return find(openList, end);
        }
    }
    //OpenList用尽,仍然找不到终点,说明终点不可到达,返回空
    return null;
}

 

JAVA代码实现待续。。。

 

A* search算法

标签:需要   程序   引入   art   sea   核心   返回   alt   current   

原文地址:http://www.cnblogs.com/shihuc/p/7636310.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!