利用栈解决迷宫问题
如图,定义起点和终点,求出从起点到终点的路径。
首先迷宫分为两种格子,一种是空白格子视为可移动格子。一种黑色格子,视为墙壁,不可移动。接着考虑如何表示移动的方向,可以使用标识符标记移动的方向,这里可以使用0,1,2,3代表上右下左四个方向。走过的格子也要标记为已考察过。考察到终点视为成功。
过程:
①将起点坐标入栈,
②根据栈顶元素0,1,2,3(上右下左)四个方向进行遍历,发现有格子不是墙,并且还未考察过,则将其入栈。
③重复②直到发现终点,或者0,1,2,3四个方向都无法移动。回溯,将栈顶元素退栈,继续②操作。
将墙体置为1,空白格子置为0。
#define M 6
#define N 6
#define MaxSize 80
int mg[M+2][N+2] = {
{1,1,1,1,1,1,1,1},
{1,0,0,0,1,0,0,1},
{1,0,1,0,1,1,0,1},
{1,0,1,1,0,0,0,1},
{1,0,1,0,0,1,0,1},
{1,0,0,0,1,1,0,1},
{1,0,1,0,1,0,0,1},
{1,1,1,1,1,1,1,1}
};
typedef struct
{
int x;
int y;
int di; //定义在坐标时本次移动方向
}Node;
typedef struct
{
Node data[MaxSize];
int top;
}SqStack;
bool MgPath(int xi,int yi,int xe,int ye)
{
int x,y,k,di,find;
SqStack s;
s.top = -1;
s.top++;
s.data[s.top].x = xi;
s.data[s.top].y = yi;
s.data[s.top].di = -1; //将访问方向置为-1,即周围坐标都未访问
mg[xi][yi] = -1; //起始点正在访问,置为-1以后就不再访问
while(s.top>-1)
{
x = s.data[s.top].x;
y = s.data[s.top].y;
di = s.data[s.top].di; //将栈顶元素取出
if(x==xe&&y==ye) //如果栈顶元素即为终点
{
printf("迷宫路径如下:\n");
for(k=0;k<=s.top;k++) //对栈中元素自底向上访问
{
printf("\t(%d,%d)",s.data[k].x,s.data[k].y);
if((k+1)%5==0)
printf("\n");
}
printf("\n");
return true;
}
find = 0;
while(di<4&&find==0) //循环直到找到四周能访问的坐标,或者四周坐标都无法访问
{
di++; //对下一个方向的坐标进行访问
switch(di)
{
case 0:
x = s.data[s.top].x-1;
y = s.data[s.top].y;
break;
case 1:
x = s.data[s.top].x;
y = s.data[s.top].y+1;
break;
case 2:
x = s.data[s.top].x+1;
y = s.data[s.top].y;
break;
case 3:
x = s.data[s.top].x;
y = s.data[s.top].y-1;
break;
}
if(mg[x][y]==0) //若该坐标为0,即为空格并且未被访问
find = 1; //将访问到坐标置为1
}
if(find==1) //将访问的坐标入栈
{
s.data[s.top].di = di;
s.top++;
s.data[s.top].x = x;
s.data[s.top].y = y;
s.data[s.top].di = -1;
ma[x][y] = -1; //访问过的坐标置为-1
}
else //若四周未找到可访问坐标,则进行回溯
{
//mg[s.data[s.top].x][s.data[s.top].y] = 0;
s.top--;
}
}
return false;
}
用栈实现迷宫问题,对应的是DFS深度优先遍历,只要找到周围一个能访问的节点,就进行访问,再访问该节点的周围节点,找到即访问,一路走到黑的赶脚。