回溯法(探索与回溯法)是一种选优搜索法,又称为试探法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为“回溯点”。
本文使用回溯法求解迷宫问题
迷宫问题,有一个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);
}