迷宫问题 (上)栈 回溯法
2013-06-30 16:16
267 查看
迷宫问题的总体思路是,从迷宫的入口出发,沿着某一个方向向前试探,若能够行得通,则继续往前走,否则原来返回,再换另一个方向继续试探,直到所有可能的通路都被试探过,为了保证在任何一个位置都能够原来返回,需要设置一个堆栈结构来保存从入口到当前位置的路径。因为可以需要保证能够返回所在节点,所以需要回溯法能够保证回到走过的节点。
本文的解法 参考 《数据结构 C》 李春葆 - 非迭代法, 迭代法 原创。迷宫用二维数组 A 表示: 最外围的1 表示墙, 内部1表示墙, 0 表示通路。使用非迭代方法, C程序如下
使用迭代方法
上述迭代方法 没有办法找到最优解(最短路径)。
只能找到所有路径。
比较上述两个方法
迭代方法 用时303ms; 非迭代方法587ms
迭代方法明显优于非迭代方法,并且易于理解。
本文的解法 参考 《数据结构 C》 李春葆 - 非迭代法, 迭代法 原创。迷宫用二维数组 A 表示: 最外围的1 表示墙, 内部1表示墙, 0 表示通路。使用非迭代方法, C程序如下
int findPath(int in_x, int in_y, int out_x, int out_y) { int A[10][10] = { {1,1,1,1,1,1,1,1,1,1}, {1,0,0,1,0,0,0,1,0,1}, {1,0,0,1,0,0,0,1,0,1}, {1,0,0,0,0,1,1,0,0,1}, {1,0,1,1,1,0,0,0,0,1}, {1,0,0,0,1,0,0,0,0,1}, {1,0,1,0,0,0,1,0,0,1}, {1,0,1,1,1,0,1,1,0,1}, {1,1,0,0,0,0,0,0,0,1}, {1,1,1,1,1,1,1,1,1,1} }; // 栈用于存储走过的节点 struct { int x; int y; int next; // how many ways to go or left to go in this node }st[MAXSTACKSIZE]; int top = -1; // 将入口添加到栈中 top++; st[top].x = in_x; st[top].y = in_y; st[top].next = -1; A[in_x][in_y] = -1; int cnt_i, cnt_j, cnt_next, find_way; while(top > -1) { cnt_i = st[top].x; cnt_j = st[top].y; cnt_next = st[top].next; // 取得当前节点 同时查看当前节点还有几个下一个节点可以走 //printf("at [%d %d]\n", cnt_i, cnt_j); // find the path if(cnt_i == out_x && cnt_j == out_y) { printf("\n\nFind the path:"); for(int k = 0; k <= top; k++) { printf("\t[%d %d]", st[k].x, st[k].y); if(k % 5 == 0) { printf("\n"); } } printf("\n\n"); } // end of find path // find next way to go find_way = 0; while(cnt_next < 4 && find_way == 0) { cnt_next++; switch(cnt_next) { case 0: cnt_i = st[top].x - 1; cnt_j = st[top].y; break; case 1: cnt_i = st[top].x; cnt_j = st[top].y + 1; break; case 2: cnt_i = st[top].x + 1; cnt_j = st[top].y; break; case 3: cnt_i = st[top].x; cnt_j = st[top].y - 1; break; } if(0 == A[cnt_i][cnt_j]) find_way = 1; // 有路可以走 } if(find_way == 1) { // find way and stack it st[top].next = cnt_next; top++; st[top].x = cnt_i; st[top].y = cnt_j; st[top].next = -1; A[cnt_i][cnt_j] = -1; }else { // do not find way in this node; // pop out the node A[st[top].x][st[top].y] = 0; top --; } } return 0; // no way to go and return 0; }
使用迭代方法
int top_iter; int A_iter[10][10] = { {1,1,1,1,1,1,1,1,1,1}, {1,0,0,1,0,0,0,1,0,1}, {1,0,0,1,0,0,0,1,0,1}, {1,0,0,0,0,1,1,0,0,1}, {1,0,1,1,1,0,0,0,0,1}, {1,0,0,0,1,0,0,0,0,1}, {1,0,1,0,0,0,1,0,0,1}, {1,0,1,1,1,0,1,1,0,1}, {1,1,0,0,0,0,0,0,0,1}, {1,1,1,1,1,1,1,1,1,1} }; int find_way_iter = 0; int findPathIterative(int in_x, int in_y, int out_x, int out_y) { top_iter = -1; top_iter++; st_iter[top_iter].x = in_x; st_iter[top_iter].y = in_y; A_iter[in_x][in_y] = -1; _findPathIterative(in_x, in_y, out_x, out_y); if(find_way_iter == 0) { printf("No way to go"); } return 0; } void _findPathIterative(int in_x, int in_y, int out_x, int out_y) { // find the path if(in_x == out_x && in_y == out_y) { printf("\n\nFind the path:"); find_way_iter = 1; for(int k = 0; k <= top_iter; k++) { printf("\t[%d %d]", st_iter[k].x, st_iter[k].y); if(k % 5 == 0) { printf("\n"); } } printf("\n\n"); } // end of find path // up node to iterate if(A_iter[in_x - 1][in_y] == 0) { PushtoStack(in_x - 1, in_y); // push the node into stack and add covered tag _findPathIterative(in_x - 1, in_y, out_x, out_y); PopFromStack(); // pop out the node and remove the tag } // right node to iterate if(A_iter[in_x][in_y+1] == 0) { PushtoStack(in_x, in_y + 1); _findPathIterative(in_x, in_y + 1, out_x, out_y); PopFromStack(); } // bottom node to iterate if(A_iter[in_x + 1][in_y] == 0) { PushtoStack(in_x + 1, in_y); _findPathIterative(in_x + 1, in_y, out_x, out_y); PopFromStack(); } // left node to iterate if(A_iter[in_x][in_y - 1] == 0) { PushtoStack(in_x, in_y - 1); _findPathIterative(in_x, in_y - 1, out_x, out_y); PopFromStack(); } } void PopFromStack() { A_iter[st_iter[top_iter].x][st_iter[top_iter].y] = 0; // out of this node top_iter --; } void PushtoStack(int x, int y) { top_iter++; st_iter[top_iter].x = x; st_iter[top_iter].y = y; A_iter[x][y] = -1; // covered this node }
上述迭代方法 没有办法找到最优解(最短路径)。
只能找到所有路径。
比较上述两个方法
迭代方法 用时303ms; 非迭代方法587ms
迭代方法明显优于非迭代方法,并且易于理解。
相关文章推荐
- Java利用回溯思想解决迷宫问题(寻找最短路径)
- 迷宫问题----搜索算法(回溯)
- 迷宫问题(深搜+回溯)
- BFS + 回溯路径 POJ - 3984 迷宫问题
- 迷宫问题回溯算法
- C语言链栈以及回溯算法解决迷宫问题
- 回溯算法经典应用之—迷宫问题 (Java)
- 迷宫问题--非递归回溯 C语言实现
- 迷宫问题--非递归回溯 C语言实现
- 回溯法求解迷宫问题
- 回溯法解决迷宫搜索问题
- SDUT 1157 小鼠迷宫问题(水题,DFS + 回溯)
- 迷宫问题 回溯法
- 回溯法解八皇后、幕集输出、迷宫问题
- 回溯法的典型问题 八皇后 马踏棋盘 迷宫
- 回溯算法基础---皇后问题,骑士游历,迷宫求解
- POJ 3984-迷宫问题(BFS+回溯路径)
- 回溯法解迷宫问题
- 走迷宫问题:回溯法和递归法
- C++ 迷宫问题的回溯解法