[人工智能AI]之搜索-A*算法
1. 概述
这是一种经典的寻路算法;
简而言之,重点在于估算距离。
问题描述:
假设起点a, 终点b, 当前结点为n
F(n) = G(n) + H(n)
G(n)表示起点到n实际距离;
H(n)表示n到终点预估距离;
在所有结点中选择F值最小的可行节点走下去即可。
缺陷:
- 显然,A*算法的效率很大程度取决于H(n)的计算,即对未来距离的预估;
- 未完待续…
2. A*算法细节
2.1 对于H(n)估算函数的选择
曼哈顿距离:横纵坐标差之和 (推荐使用)
欧氏距离:即两点间的实际距离
ps: 这两种估算方式,会导致无法避开障碍物。
2.2 A*算法实现
"""
A*寻路算法, 评估函数采用曼哈顿距离
"""
path = [[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 3, 0, 0, 0, 0, 0],
[0, 0, 0, 3, 0, 0, 2, 0, 0],
[0, 0, 0, 3, 0, 0, 0, 0, 0],
[0, 4, 0, 3, 0, 0, 0, 0, 0],
[0, 0, 0, 3, 0, 0, 0, 0, 0],
[0, 0, 0, 3, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
]
m = len(path)
n = len(path[0])
visit = 0
a = [4, 1]
b = [2, 6]
def showNode():
for i in path:
for j in i:
print(j, end='')
print()
print()
def getNode(x):
return path[x[0]][x[1]]
def inSide(x, y):
return x>=0 and x<m and y>=0 and y<n
def isNode(x, y):
return path[x][y] == 0 or path[x][y] == 2
def getNeigh(x, y):
neigh = []
if inSide(x-1, y) and isNode(x-1, y):
neigh.append([x-1, y])
if inSide(x+1, y) and isNode(x+1,y):
neigh.append([x+1, y])
if inSide(x, y-1) and isNode(x,y-1):
neigh.append([x, y-1])
if inSide(x, y+1) and isNode(x,y+1):
neigh.append([x, y+1])
return neigh
def testNeigh(neigh):
for i in range(m):
for j in range(n):
if [i, j] in neigh:
print(' ', end='')
else:
print(path[i][j], end='')
print()
def calDist(A, B):
# 计算两点的曼哈顿距离
return abs(A[0]-B[0]) + abs(A[1]-B[1])
def update(dist, neigh):
minDist = 0x7fffffff
minXY = 0
for node in neigh: # like [3, 4]
dist[node[0]][node[1]] = visit + calDist(node, b)
if dist[node[0]][node[1]] < minDist:
minDist = dist[node[0]][node[1]]
minXY = node
return minXY
def findPath(curX, curY):
global path, visit
showNode()
if curX == b[0] and curY == b[1]:
print('Reach the End!')
return
dist = [[-1 for i in range(n)] for i in range(m)]
neigh = getNeigh(curX, curY)
XY = update(dist, neigh)
visit += 1
curX, curY = XY[0], XY[1]
path[curX][curY] = ' '
findPath(curX, curY)
# 更新
findPath(a[0], a[1])
演示结果(节选部分)如下图, 起点为4, 终点为2, 障碍物为3, 其他0表示可行点