zoukankan      html  css  js  c++  java
  • A*算法

    A*算法是一种经典的启发式搜索算法,公式表示为:f(n)=g(n)+h(n),其中f(n) 是从初始点到目标点的估价函数,g(n)是从初始点到节点n的代价,h(n)是从节 点n到目标节点的估计代价,保证找到最短路径关键在于估价函数h(n)的选取。
    一、几个相关知识:
    启发式搜索:启发式搜索就是在状态空间中的搜索对每一个搜索的位置进行评估,得到最好的位置,再从这个位置进行搜索直到目标。这样可以省略大量无畏的搜索路径,提到了效率。在启发式搜索中,对位置的估价是十分重要的。采用了不同的估价可以有不同的效果。

    估价函数:从当前节点移动到目标节点的预估费用;这个估计就是启发式的。在寻路问题和迷宫问题中,我们通常用曼哈顿(manhattan)估价函数。

    A算法的特点:A算法在理论上是时间最优的,但是也有缺点:它的空间增长是指数级别的。

    A算法与BFS:可以这样说,BFS是A算法的一个特例。对于一个BFS算法,从当前节点扩展出来的每一个节点(如果没有被访问过的话)都要放进队列进行进一步扩展。也就是说BFS的估计函数h永远等于0,没有一点启发式的信息,可以认为BFS是“最烂的”A*算法。

    IDA算法:这种算法被称为迭代加深A算法,可以有效的解决A*空间增长带来的问题,甚至可以不用到优先级队列。

    二、A*伪代码

     push startNode onto openList
        while(openList is not empty) {
            if current is goal return path
    
            remove currentNode from openList
            push currentNode onto closedList
            for each neighbor in negighbors {
                if neighbor is not in openList {
                    save g, h, and f
                    save current parent
                    add neighbor to openList
                }
                
                if neighbor is in openList
                    And g is better than previous g {
                    save g and f
                    save the current parent
                }
                
            }
        }

    三、coffeescript实现

    astar =
        init: (grid) ->
            for x in [0...grid.length]
                for y in [0...grid[x].length]
                    grid[x][y].f = 0
                    grid[x][y].g = 0
                    grid[x][y].h = 0
                    grid[x][y].debug = ""
                    grid[x][y].parent = null
                    
        search: (grid, start, end) ->
            astar.init grid
    
            openList = []
            closeList = []
            openList.push start
    
            while openList.length > 0
    
                # 获取最小的f(x)的点
                lowInd = 0
                for i in [0...openList.length]
                    lowInd = i if openList[i].f < openList[lowInd].f
                currentNode = openList[lowInd]
    
                # 到达目标点,返回路径
                if currentNode.pos is end.pos
                    curr = currentNode
                    ret = []
                    while curr.parent
                        ret.push curr
                        curr = curr.parent
                    return ret.reverse()
    
                # 最短路径搜索过程
                # 将当前点从openList移至closeList
                # 处理当前点的每个相邻点
                openList.removeGraphNode currentNode
                closeList.push currentNode
                neightbors = astar.neighbors grid, currentNode
    
                for i in [0...neighbors.length]
                    neighbor = neighbor[i]
                    if closeList.findGraphNode(neighbor) or neighbor.isWall()
                        # 无效点,跳至下一个相邻点
                        continue
    
                    # gScore 是起始点到当前点所经过的距离
                    # 需要判断当前相邻是否是最短距离
                    gScore = currentNode.g + 1 # 1是当前点到相邻点的距离
                    gScoreIsBest = false
    
                    if !openList.findGraphNode(neighbor)
                        # 第一次到达当前点, 它必是当前最短距离
                        # 并且,需要计算 h(x) 
                        gScoreIsBest = true
                        neighbor.h = astar.heuristic neighbor.pos, end.pos
                        openList.push neighbor
                    else if gScore < neighbor.g
                        # 已经到达过该点,并且路径短于上次
                        gScoreIsBest = true
    
                    if gScoreIsBest
                        # 找到当前的最短路径,将它保存起来
                        neighbor.parent = currentNode
                        neighbor.g = gScore
                        neighbor.f = neighbor.g + neighbor.h
                        neighbor.debug = "F: " + neighbor.f +
                            "
    G: " + neighbor.g + "
    H:" + neighbor.h
    
            # 未找到最短路径,返回空
            return []
            
        heuristic: (pos0, pos1) ->
            return Math.abs(pos1.x - pos0.x) + Math.abs(pos1.y -pos0.y)
            
        neighbors: (grid, node) ->
            ret = []
            x = node.pos.x
            y = node.pos.y
    
            ret.push grid[x-1][y] if grid[x-1]?[y]? 
            ret.push grid[x+1][y] if grid[x+1]?[y]? 
            ret.push grid[x][y-1] if grid[x]?[y-1]? 
            ret.push grid[x][y+1] if grid[x]?[y+1]? 

    参考:
    A* search algorithm description on wiki
    astar-search-algorithm-in-javascript
    vistual PathFinding.js
    A*算法入门

  • 相关阅读:
    论财务的意义
    项目忙乱的原因
    回家的路
    但问耕耘
    做自己的主角
    坚持的意义
    觉醒的意义
    梦想的力量
    把自己当作一件艺术品
    九宫格年度计划
  • 原文地址:https://www.cnblogs.com/arcticant/p/4593369.html
Copyright © 2011-2022 走看看