博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
路径搜索算法-A星算法
阅读量:4126 次
发布时间:2019-05-25

本文共 6994 字,大约阅读时间需要 23 分钟。

A*算法的核心就是f(M)=g(M)+h(M),g(M)表示当前节点到初始节点的最短路径大小,h(M)表示当前节点到终止节点的可能路径大小(即虚拟的,如欧氏距离,曼哈顿距离等)。即不仅仅考虑当前节点到初始节点的最短路径,还要考虑离终点的距离。而一般的路径查找方法只会考虑当前节点到初始节点的路径

路径选择

两个关键集合open和close

open和close
简单一句话即:open 往close 插入元素

open:已经搜索的区域

close:比较已经搜索的区域中的数值f,找到最好的插入close
即close中保存的是最短路径节点,open中是待选节点

""" @author: zoutai@file: Astar.py @time: 2018/04/23 @description: """# 地图import mathmapStr = [    '############################################################',    '#..........................................................#',    '#.............................#............................#',    '#.............................#............................#',    '#.............................#............................#',    '#.......S.....................#............................#',    '#.............................#............................#',    '#.............................#............................#',    '#.............................#............................#',    '#.............................#............................#',    '#.............................#............................#',    '#.............................#............................#',    '#.............................#............................#',    '#######.#######################################............#',    '#....#........#............................................#',    '#....#........#............................................#',    '#....##########............................................#',    '#..........................................................#',    '#..........................................................#',    '#..........................................................#',    '#..........................................................#',    '#..........................................................#',    '#...............................##############.............#',    '#...............................#........E...#.............#',    '#...............................#............#.............#',    '#...............................#............#.............#',    '#...............................#............#.............#',    '#...............................###########..#.............#',    '#..........................................................#',    '#..........................................................#',    '############################################################']class Node:    """    用于节点的表示,parent用来在成功的时候回溯路径(相当于一个链表)    """    def __init__(self, parent, x, y, dist):        self.parent = parent        self.x = x        self.y = y        self.dist = dist # 这里只是g(M)class A_Star:    # 初始化地图长和宽,开始终止节点,open集合和close集合,    # 路径集合path用于最后反向遍历找出路径    def __init__(self, start, end, w=60, h=30):        self.start = start        self.end = end        self.width = w        self.height = h        self.open = []        self.close = []        self.path = []    def find_path(self):        # 1、初始化开始节点        p = Node(None, self.start[0], self.start[1], 0.0)        while True:            # 扩展F值最小的节点            self.extend_round(p)            # 如果开open列表为空,表示能走的路全走完了,无法走了,表示不存在路径,返回(封闭空间)            if not self.open:                return            # 获取F值最小的节点(最短路径)            idx, p = self.get_best()            # 如果是终点,直接返回            if self.end[0]==p.x and self.end[1]==p.y:                # 画路径                while p:                    self.path.append((p.x, p.y))                    p = p.parent                return            # 不是终点,则将此节点压入关闭列表,并从开放列表里删除(即这是最好的节点)            self.close.append(p)            del self.open[idx]    def extend_round(self, p):        # 可以从8个方向走        xs = (-1, 0, 1, -1, 1, -1, 0, 1)        ys = (-1, -1, -1, 0, 0, 1, 1, 1)        # 只能走上下左右四个方向        #        xs = (0, -1, 1, 0)        #        ys = (-1, 0, 0, 1)        for x, y in zip(xs, ys):            new_x, new_y = x + p.x, y + p.y            # 判断1:是否越界或者撞墙            if new_x < 0 or new_x >= self.width or new_y < 0 or new_y >= self.height \                    or MapData[new_y][new_x] == '#':                continue            # 生成新的节点和g(M)值,get_cost可以默认为1,这里为了考虑斜线和直线不同            newNode = Node(p, new_x, new_y, p.dist+self.get_cost(p,new_x,new_y))            # 新节点在close列表中,表示回环了,之前路径更好,忽略当前节点            # 比如c:a->b->c->b            if self.node_in_close(newNode):                continue            # 新节点是否在open列表中            i = self.node_in_open(newNode)            # -1:如果不在,比较更新open中的此节点数值            if i!=-1:                if self.open[i].dist > newNode.dist:                    self.open[i].parent = p                    self.open[i].dist = newNode.dist                continue            # 否则,则加入open列表,用于备选比较            # 将新节点放入open中(第一次访问)            self.open.append(newNode)    def get_best(self):        best = None        bv = 1000000  # 如果你修改的地图很大,可能需要修改这个值        bi = -1        for idx, i in enumerate(self.open):            f = i.dist + math.sqrt(                (self.end[0] - i.x) * (self.end[0] - i.x)                + (self.end[1] - i.y) * (self.end[1] - i.y)) * 1.2            value = f  # 获取F值            if value < bv:  # 比以前的更好,即F值更小                best = i                bv = value                bi = idx        return bi, best    def get_searched(self):        searched = []        for i in self.open:            searched.append((i.x, i.y))        for i in self.close:            searched.append((i.x, i.y))        return searched    def get_cost(self, p, new_x, new_y):        """        上下左右直走,代价为1.0,斜走,代价为1.4        """        if p.x == new_x or p.y == new_y:            return 1.0        return 1.4    def node_in_close(self, node):        for i in self.close:            if node.x == i.x and node.y == i.y:                return True        return False    def node_in_open(self, node):        for i, n in enumerate(self.open):            if node.x == n.x and node.y == n.y:                return i        return -1# 查找字符所在位置def get_symbol_XY(s):    for y, line in enumerate(MapData):        try:            x = line.index(s)        except:            continue        else:            break    return [x, y]def search():    # 初始化整个程序    a_star = A_Star(START, END,len(MapData[0]),len(MapData))    # 从开始几点查找路径    a_star.find_path()    # 标记已搜索区域为'-'    # 已搜索区域=open+close    searched = a_star.get_searched()    for x, y in searched:        MapData[y][x] = '-'    # 标记路径为'>'    path = a_star.path    for x, y in path:        MapData[y][x] = '>'    # 打印最短路径长度和搜索区域长度    print("path length is %d" % (len(path)))    print("searched squares count is %d" % (len(searched)))    # 恢复开始和终止节点的标记    MapData[START[1]][START[0]] = 'S'    MapData[END[1]][END[0]] = 'E'if __name__ == '__main__':    # 因为python里string不能直接改变某一元素,所以用MapData来存储搜索时的地图    MapData = []    for line in mapStr:        MapData.append(list(line))    # 初始化起始和终点坐标[x,y]    START = get_symbol_XY('S')    END = get_symbol_XY('E')    # 开始搜索路径    search()    # 打印搜索后的地图    for line in MapData:        print(''.join(line))

参考:

转载地址:http://phepi.baihongyu.com/

你可能感兴趣的文章
Palindrome Partitioning --回文切割 深搜(重重)
查看>>
Valid Palindrome 简单的回文判断
查看>>
Pascal's Triangle -- 生成杨辉三角
查看>>
Pascal's Triangle II 生成杨辉三角中的某行
查看>>
Minimum Depth of Binary Tree -- 二叉树的最小深度 DFS 加剪枝
查看>>
Climbing Stairs 爬楼梯方法 动态规划
查看>>
Merge Two Sorted Lists 合并两个有序链表
查看>>
pow(x,n) 为什么错这么多次
查看>>
Jump Game 动态规划
查看>>
Subsets 深搜
查看>>
Subsets II
查看>>
Edit Distance 字符串距离(重重)
查看>>
Gray Code 格雷码
查看>>
对话周鸿袆:从程序员创业谈起
查看>>
web.py 0.3 新手指南 - 如何用Gmail发送邮件
查看>>
web.py 0.3 新手指南 - RESTful doctesting using app.request
查看>>
web.py 0.3 新手指南 - 使用db.query进行高级数据库查询
查看>>
web.py 0.3 新手指南 - 多数据库使用
查看>>
一步步开发 Spring MVC 应用
查看>>
python: extend (扩展) 与 append (追加) 的差别
查看>>