算法之使用递归求解迷宫问题

算法之使用递归求解迷宫问题

题目要求:

现有一个迷宫,四周都被围起来了,只能从一个入口进入,计算出一条通道使得从入口可以安全到达出口。在迷宫中行走的方向可以是(北,东北,东,东南,南,西南,西,西北)八个方向,迷宫图案如下:

 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)
源代码