路径规划问题:A*算法 以及Python实现
参考:
https://www.geeksforgeeks.org/a-search-algorithm/
https://www.101computing.net/a-star-search-algorithm/
一. 概述:
A*算法是一种包含了启发的Djkstra算法,可以用来求带权值的图的最短路径。
A*算法比起Djkstra算法,在寻找最短路径的问题上更加有效率。
算法中,引入了距离作为启发,通过终点和节点的距离计算,选择迭代的点。
通常求距离有以下几种方案:
1. 曼哈顿距离
h = abs (current_cell.x – goal.x) + abs (current_cell.y – goal.y)
2. 对角线距离
h = max { abs(current_cell.x – goal.x), abs(current_cell.y – goal.y) }
3. 欧氏距离
h = sqrt ( (current_cell.x – goal.x)2 + (current_cell.y – goal.y)2 )
二. 示例:
以下示例介绍运用A*算法的详细步骤,假设图如下,求A到Z的最短路径,各节点与Z的距离已经求得,下图中标为橙色。
第一步:
初始化数据表如下,初始化每个节点到A的最短距离为无穷大
第二步:
以A为当前点,求出以A为起点的两条路径,并更新数据表。更新Total Distance为已计算的最短距离 + 与Z的启发距离
第三步:
由于C的Total Distance小于b,从c开始计算并更新e和d的距离
第四步:
B和D的Total Distance一样,我们从B开始迭代,进一步更新数据表
第五步:
第六步:
第七步:
迭代到Z,获得最小距离。最小路径可以从Z的前一个节点向前追溯,得到路径A-C-D-E。
最后再遍历没有访问的节点F,由于F的Total Distance > 17, 则不可能是最短路径节点。
三. Python代码实现:
1 #!/usr/bin/python3 2 # -*- coding: utf-8 -*- 3 # @author: Asp1rant 4 5 6 # 存放中间数据的数据结构 7 class PriorityData: 8 visited = False 9 shortest_distance_start = 0 10 heuristic_distance_end = 0 11 total_distance = 0 12 previous_node = '' 13 14 def __init__(self, heuristic_value): 15 self.heuristic_distance_end = heuristic_value 16 self.shortest_distance_start = 9999 17 self.total_distance = 9999 18 19 20 def a_star(graph, heuristic_value, start, end): 21 priority_dic = {} 22 for k in graph.keys(): 23 priority_dic[k] = PriorityData(heuristic_value[k]) 24 priority_dic[start].shortest_distance_start = 0 25 26 # 判断终点是否访问 27 def isEndVisited(): 28 ret = False 29 if priority_dic[end].visited: 30 distance = priority_dic[end].total_distance 31 ret = True 32 return ret 33 34 # 更新节点数据表 35 def updateNode(node): 36 neighbors = graph[node] 37 for k in neighbors.keys(): 38 neighbor_data = priority_dic[k] 39 if priority_dic[node].shortest_distance_start + neighbors[k] < neighbor_data.shortest_distance_start: 40 neighbor_data.shortest_distance_start = priority_dic[node].shortest_distance_start + neighbors[k] 41 neighbor_data.total_distance = neighbor_data.shortest_distance_start + neighbor_data.heuristic_distance_end 42 neighbor_data.previous_node = node 43 priority_dic[node].visited = True 44 45 find_point = start 46 while not isEndVisited(): 47 updateNode(find_point) 48 shortest_distance = 9999 49 for k in priority_dic.keys(): 50 if not priority_dic[k].visited and priority_dic[k].total_distance < shortest_distance: 51 find_point = k 52 shortest_distance = priority_dic[k].total_distance 53 54 path_node_list = [end] 55 result_distance = priority_dic[end].total_distance 56 previous_node = priority_dic[end].previous_node 57 while previous_node != start: 58 path_node_list.append(previous_node) 59 previous_node = priority_dic[previous_node].previous_node 60 path_node_list.append(start) 61 path = path_node_list[len(path_node_list) - 1] 62 for i in range(len(path_node_list)-2, -1, -1): 63 path += "-" 64 path += path_node_list[i] 65 return (path, result_distance) 66 67 68 if __name__ == '__main__': 69 # 用于测试的图 70 graph = { 71 "A": {"B": 4, "C": 3}, 72 "B": {"E": 12, "F": 5}, 73 "C": {"E": 10, "D": 7}, 74 "D": {"E": 2}, 75 "E": {"Z": 5}, 76 "F": {"Z": 16}, 77 "Z": {} 78 } 79 heuristic_value = {"A": 14, "B": 12, "C": 11, "D": 6, "E": 4, "F": 11, "Z": 0} 80 result = a_star(graph, heuristic_value, "A", "Z") 81 print(result)
结果:
('A-C-D-E-Z', 17)
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析