回溯法求迷宮問題
阿新 • • 發佈:2019-02-01
回溯法(探索與回溯法)是一種選優搜尋法,又稱為試探法,按選優條件向前搜尋,以達到目標。但當探索到某一步時,發現原先選擇並不優或達不到目標,就退回一步重新選擇,這種走不通就退回再走的技術為回溯法,而滿足回溯條件的某個狀態的點稱為“回溯點”。
本文使用回溯法求解迷宮問題
迷宮問題,有一個m行n列的矩陣代表迷宮,1代表此路不通,0代表此路通。指定入口和出口,判斷是否能從入口進,從出口走出。此程式只判斷從路口到出口是否能走通,找到的路不一定是最短路(最短路的程式在下一篇中使用BFS演算法給出),注意:從入口到出口可能沒有路徑或者不止一條路徑。此處迷宮走法是8個方向,分別是左上,上,右上,右,右下,下,左下,左。程式中使用offsets myMove給出八個方向的表示。
#include <iostream> #include <stack> using namespace std; struct offsets { int a,b;//a,b是x,y方向的偏移 char* dir;//dir方向 }; offsets myMove[8] = {//各個方向的偏移表 {-1,0,"N"}, {-1,1,"NE"}, {0,1,"E"}, {1,1,"SE"}, {1,0,"S"}, {1,-1,"SW"}, {0,-1,"W"}, {-1,0-1,"NW"} }; struct items { int x,y,dir;//位置和前進方向的序號 }; const int MAXNUM = 5; int mark[MAXNUM][MAXNUM] = {0};//標記陣列 int Maze[MAXNUM][MAXNUM] = { 1,1,1,1,1, 1,0,1,0,1, 1,0,0,1,1, 1,1,1,0,1, 1,1,1,1,1 }; //迷宮 void printPath(stack<items>& st) { int num = st.size(); for (int index = 0; index < num; index++) { items tmpIt = st.top(); cout<<"("<<tmpIt.x<<","<<tmpIt.y<<","<<tmpIt.dir<<")"<<"<-"; st.pop(); } cout<<endl; } void Mypath(int m,int p) { int flag = 0; int Currx,Curry,Currd,Searchx,Searchy; mark[1][1] = 1;//(1,1)是入口 stack<items> st; items tmp; tmp.x = 1,tmp.y = 1,tmp.dir = 2; st.push(tmp); while (! st.empty()) { if (flag == 1) { st.pop(); } flag = 0; items tmpItems = st.top(); Currx = tmpItems.x,Curry = tmpItems.y,Currd = tmpItems.dir; while (Currd < 8) { Searchx = Currx + myMove[Currd].a,Searchy = Curry + myMove[Currd].b; if (Maze[Searchx][Searchy] == 0 && mark[Searchx][Searchy] == 0) { flag = 1; mark[Searchx][Searchy] = 1; tmp.x = Searchx,tmp.y = Searchy,tmp.dir = Currd; st.push(tmp); Currx = Searchx;Curry = Searchy; Currd = 0; } else { Currd++; } if (Searchx == m && Searchy == p) { cout<<m<<" "<<p<<endl; cout<<"("<<m<<","<<p<<","<<Currd<<")"<<"<-"; printPath(st); return; } } } cout<<"no path in Maze"<<endl; } int main() { Mypath(2,1); }