回溯思想解决迷宫问题
这是几个由二维数组构成的迷宫,简单的迷宫,多通路不带环的迷宫,多通路带环的迷宫!对于简单迷宫我们需要判断是否有出口!对于多通路不带环的迷宫我们需要确定出口并且判断最短路径,对于通路间带环的迷宫我们需要找出最短路径!
算法思想:回溯
回溯算法实际上一个类似枚举的搜索尝试过程,主要是在搜索尝试过程中寻找问题的解,当发现已不满足求解条件时,就“回溯”返回,尝试别的路径。回溯法是一种选优搜索法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为“回溯点”。 在本题中也用到的就是回溯, 就是把走过的点坐标压栈,遇到无路可走的情况就开始回溯,也就是出栈! 总体思路就是:
- 现将入口点压栈,走过的地方标记为2
- 每走一步就将坐标压栈,判断下一步可以走的地方,如果能走就压栈
- 当上下左右四个方向都不能走的时候就回溯
- 直到回溯到入口点还是没有其他方向可以走,那么循环结束,也就意味着没有出口!
- 使用一个方法判断坐标点是否合法的,注意数组越界的情况,首先不越界,其次坐标点值为1的时候才是合法的
- 对于多通路迷宫首先需要明白当右边出现两个入口点的时候只需要判断
列 == N
即可认为是找到了出口 - 首先下一个点可以走的条件是:该点值为1或者该点值比上一个+1还大
- 每走一步值就+1,入口点值设置为2
代码实现
所有代码位于GitHub:https://github.com/zouchanglin/VSworkspace/tree/master/67_Maze,对于简单迷宫的核心代码:
1int CheckAccess(Pos next)
2{
3 //判断越界的情况
4 if(next._col >= 0 &&next._row>=0
5 && next._col<N && next._row<N)
6 {
7 //1才是表示通路
8 if (maze[next._row][next._col] == 1)
9 {
10 return 1;
11 }
12 }
13 //return 0表示不可以通过
14 return 0;
15}
16int MazeGetPath(Pos entry,Pos exit)
17{
18 Pos cur = entry;//cur记录起始位置
19
20 Stack path;
21 StackInit(&path);
22 StackPush(&path, entry);//将起始坐标压栈
23 while (StackEmpty(&path))
24 {
25 cur = StackTop(&path);
26 if ((cur._row == exit._row) && (cur._col == exit._col))
27 return 1;
28 //探测下一次可以去的地方
29 maze[cur._row][cur._col] = 2;//标记上一次走过的位置
30 //上
31 Pos next = cur;
32 next._row -= 1;
33 if (CheckAccess(next))
34 {
35 StackPush(&path, next);
36 continue;
37 }
38 //下
39 next = cur;
40 next._row += 1;
41 if (CheckAccess(next))
42 {
43 StackPush(&path, next);
44 continue;
45 }
46 //左
47 next = cur;
48 next._col -= 1;
49 if (CheckAccess(next))
50 {
51 StackPush(&path, next);
52 continue;
53 }
54 //右
55 next = cur;
56 next._col += 1;
57 if (CheckAccess(next))
58 {
59 StackPush(&path, next);
60 continue;
61 }
62
63 //回溯
64 StackPop(&path);
65 }
66 return 0;
67}
对于稍复杂的迷宫的核心代码
1int CheckAccess(Pos next)
2{
3 //判断越界的情况
4 if(next._col >= 0 &&next._row>=0
5 && next._col<N && next._row<N)
6 {
7 //1才是表示通路
8 if (maze[next._row][next._col] == 1)
9 {
10 return 1;
11 }
12 }
13 //return 0表示不可以通过
14 return 0;
15}
16
17int MazeCheckIsAccess(Pos cur, Pos next)
18{
19 //判断越界的情况
20 if ((next._col >= 0 && next._row >= 0 && next._col<N && next._row<N)
21 &&(maze[next._row][next._col] == 1 || maze[next._row][next._col]>maze[cur._row][cur._col]+1))
22 {
23 return 1;
24 }
25 //return 0表示不可以通过
26 return 0;
27}
28
29int pathsize = 0;
30
31int MazeGetPath(Pos entry,Pos exit)
32{
33 Pos cur = entry;//cur记录起始位置
34
35 Stack path;
36 StackInit(&path);
37 StackPush(&path, entry);//将起始坐标压栈
38
39 maze[entry._row][entry._col] = 2;
40 while (StackEmpty(&path))
41 {
42 cur = StackTop(&path);
43 maze[cur._row][cur._col] = 2;//标记上一次走过的位置
44 //if ((cur._row == exit._row) && (cur._col == exit._col))
45 if (cur._col == 5)
46 {
47 //如果只找一条通路则返回
48 //return 1;
49 //StackDestory(&path);
50 if (pathsize == 0||
51 StackSize(&path) < pathsize)
52 {
53 pathsize = StackSize(&path);
54 }
55 }
56 //探测下一次可以去的地方
57 //上
58 Pos next = cur;
59 next._row -= 1;
60 if (CheckAccess(next))
61 {
62 StackPush(&path, next);
63 continue;
64 }
65 //下
66 next = cur;
67 next._row += 1;
68 if (CheckAccess(next))
69 {
70 StackPush(&path, next);
71 continue;
72 }
73 //左
74 next = cur;
75 next._col -= 1;
76 if (CheckAccess(next))
77 {
78 StackPush(&path, next);
79 continue;
80 }
81 //右
82 next = cur;
83 next._col += 1;
84 if (CheckAccess(next))
85 {
86 StackPush(&path, next);
87 continue;
88 }
89
90 //回溯
91 StackPop(&path);
92 }
93 return 0;
94}
95
96
97int MazeGetShortPath(Pos entry, Pos exit)
98{
99 Pos cur = entry;//cur记录起始位置
100
101 Stack path;
102 StackInit(&path);
103 StackPush(&path, entry);//将起始坐标压栈
104
105
106 maze[entry._row][entry._col] = 2;
107 while (StackEmpty(&path))
108 {
109 cur = StackTop(&path);
110 if (cur._col == 5)
111 {
112 //如果只找一条通路则返回
113 //return 1;
114 //StackDestory(&path);
115 if (pathsize == 0 ||
116 StackSize(&path) < pathsize)
117 {
118 pathsize = StackSize(&path);
119 }
120 }
121 //探测下一次可以去的地方
122 //上
123 Pos next = cur;
124 next._row -= 1;
125 if (MazeCheckIsAccess(cur, next))
126 {
127 maze[next._row][next._col] = maze[cur._row][cur._col] + 1;
128 StackPush(&path, next);
129 continue;
130 }
131 //下
132 next = cur;
133 next._row += 1;
134 if (MazeCheckIsAccess(cur, next))
135 {
136 maze[next._row][next._col] = maze[cur._row][cur._col] + 1;
137 StackPush(&path, next);
138 continue;
139 }
140 //左
141 next = cur;
142 next._col -= 1;
143 if (MazeCheckIsAccess(cur, next))
144 {
145 maze[next._row][next._col] = maze[cur._row][cur._col] + 1;
146 StackPush(&path, next);
147 continue;
148 }
149 //右
150 next = cur;
151 next._col += 1;
152 if (MazeCheckIsAccess(cur, next))
153 {
154 maze[next._row][next._col] = maze[cur._row][cur._col] + 1;
155 StackPush(&path, next);
156 continue;
157 }
158
159 //回溯
160 StackPop(&path);
161 }
162 return 0;
163}