前言
刷到一道算法笔试题,求在有障碍的“棋盘”上任意两点最短路径。
题目描述
如图为一个10*10的网格图,黑点处为障碍物,给定任意两点——start和end,求最短路径,走一格距离为1。
Code
# 算法思想:通过BFS找end,找到就停
# 部分变量含义:
# value->网格图列表
# hinders->障碍点坐标列表
# visit->访问点及对应距离的字典
# lis->用于bfs的队列
def inHinder(point, hinders):
if point in hinders:
return True
else:
return False
def findMinPath(start , end, hinders):
start = tuple(start)
end = tuple(end)
# 存储访问过的点和对应距离
visit = dict()
visit[start] = 0
# 建立队列,使用广度优先搜索
lis = list()
lis.append(start)
while 1 :
tmp = lis[0]
tmp = list(tmp)
tmp[1] += 1
UP = tuple(tmp)
tmp[1] -= 2
DOWN = tuple(tmp)
tmp = lis[0]
tmp = list(tmp)
tmp[0] -= 1
LEFT = tuple(tmp)
tmp[0] += 2
RIGHT = tuple(tmp)
tmp = lis[0]
if UP not in visit and inHinder(UP, hinders) == False:
lis.append(UP)
visit[UP] = visit[tmp] + 1
if DOWN not in visit and inHinder(DOWN, hinders) == False:
lis.append(DOWN)
visit[DOWN] = visit[tmp] + 1
if LEFT not in visit and inHinder(LEFT, hinders) == False:
lis.append(LEFT)
visit[LEFT] = visit[tmp] + 1
if RIGHT not in visit and inHinder(RIGHT, hinders) == False:
lis.append(RIGHT)
visit[RIGHT] = visit[tmp] + 1
# 出队
lis.pop(0)
# end被访问,跳出循环
if end in visit:
break
return visit[end]
def main():
hinders = set()
value = [
0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
0, 0, 0, 0, 0, 0, 1, 1, 0, 0,
0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
0, 0, 0, 1, 1, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 1, 1, 1, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
0, 1, 0, 0, 0, 1, 0, 0, 0, 0,
0, 1, 1, 1, 1, 0, 0, 0, 0, 0,
0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0
]
for i in range(len(value)):
if value[i] == 1:
tmpx = i % 10
tmpy = 10 - i // 10 - 1
tmp = list()
tmp.append(tmpx)
tmp.append(tmpy)
tmp = tuple(tmp)
hinders.add(tmp)
print(findMinPath(start=[1,1], end=[2,3], hinders=hinders))
if __name__ == '__main__':
main()