算法之使用递归求解迷宫问题
题目要求:
现有一个迷宫,四周都被围起来了,只能从一个入口进入,计算出一条通道使得从入口可以安全到达出口。在迷宫中行走的方向可以是(北,东北,东,东南,南,西南,西,西北)八个方向,迷宫图案如下:
1 [ 2 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 3 [0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1], 4 [1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1], 5 [1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1], 6 [1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1], 7 [1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1], 8 [1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1], 9 [1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1], 10 [1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1], 11 [1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1], 12 [1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1], 13 [1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1], 14 [1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0], 15 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 16 ]
入口位置在第二行第一列的位置,出口位置在倒数第二行最后一列的位置。中间是0的位置表示可以到达,其他位置被堵死。
解决思路:
假设在该迷宫中的某一点,其有八个方向可供选择,那么,遍历这八个方向,探测这周边八个方向是否是可达的,如果可达,那再以可达的点为当前点,继续遍历八个方向检测其周边的方向是否可达。设置一个标记表,只要是走过的点,都将标记位设置为1,这样是为了不走之前走过的老路。这样递归下去,直到到达我们想要出去的迷宫的出口处位置时,到达递归的最大深度,之后一层一层反向打印出之前走过的位置。。。
1 #!/usr/bin/env python 2 # encoding:utf-8 3 # __author__: huxianglin 4 # date: 2016-09-04 5 # blog: http://huxianglin.cnblogs.com/ http://xianglinhu.blog.51cto.com/ 6 7 MAZE = [ 8 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 9 [0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1], 10 [1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1], 11 [1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1], 12 [1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1], 13 [1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1], 14 [1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1], 15 [1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1], 16 [1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1], 17 [1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1], 18 [1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1], 19 [1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1], 20 [1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0], 21 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 22 ] 23 24 MOVE = [[0, -1, "N"], [1, -1, "NE"], [1, 0, "E"], [1, 1, "SE"], [0, 1, "S"], [-1, 1, "SW"], [-1, 0, "W"], 25 [-1, -1, "NW"]] 26 27 28 def seek_path(x, y): # x,y作为横纵坐标传递进来 29 if x == LINE-1 and y == ROW-2: # 出口地址 30 return True 31 for i in range(8): # 循环找八个方向看哪个方向有路 32 line, row, direction = x+MOVE[i][0], y+MOVE[i][1], MOVE[i][2] # 将当前位置的移动后的坐标以及移动方向赋值给新变量用来递归 33 if MAZE[row][line] == 0 and mark[row][line] == 0: # 移动后的坐标是通的并且之前没走过 34 mark[row][line] = 1 # 将该新位置坐标标记为已走过 35 if seek_path(line, row): # 将新坐标传递到递归函数中进行下一步递归 36 print("横向移动:%s,纵向移动:%s,方向:%s" % (MOVE[i][0], MOVE[i][1], direction)) 37 path.append(["横向移动:%s" % MOVE[i][0], "纵向移动:%s" % MOVE[i][1], "方向:%s" % direction, 38 "坐标:(%s,%s)" % (line, row)]) 39 return True 40 41 if __name__ == "__main__": 42 LINE, ROW = len(MAZE[0]), len(MAZE) 43 mark = [] 44 # for i in range(14): 45 # mark.append([0 for j in range(17)]) 46 mark = [[0 for v in range(len(MAZE[0]))] for m in range(len(MAZE))] # 列表推导试生成mark列表 47 path = [] 48 mark[1][0] = 1 49 if seek_path(0, 1): 50 print("迷宫走完了...下面是每一步的详细情况:") 51 path.reverse() 52 for i in path: 53 print(i)