问题描述:以一个m×n的长房阵表示迷宫,0和1分别表示通路和障碍,求出一条从入口到出口的通路,或者输出“此迷宫没有通路”
思路:利用栈记录每个单元格的坐标和每次选取的路径方向,对单元格上下左右四个方向依次试探来寻取不同的路径。同时每次找到一条路径就记录路径长度,然后下次找到新的路径比较前者的路径长度从而刷新最短路径(具体见代码)
上代码:
/***
11.2.17 迷宫问题
--2022.5.10.14:41
***/
#include<stdio.h>
#define MAXSIZE 100
#define endX 9 //迷宫行数
#define endY 8 //迷宫列数
typedef struct mg
{
int x; //记录每个可走结点的横坐标
int y; //记录每个可走结点的纵坐标
int dir; //记录每个节点下一次选择路径的方向(0:上,1:右,2:下,3:左)
}Stackmg[MAXSIZE],Pathmg[MAXSIZE];
int top=0; //栈顶指针(始终指向栈顶元素的下一个空位置),同时看出top也是栈内元素个数
int minlength=MAXSIZE; //minlength记录最短路径
Stackmg maze; //作为栈,记录访问点的坐标,选路方向
Pathmg shortestPath; //存储最短路径
int map[endX+2][endY+2] //迷宫地图信息(9×8的地图)
={
//这里在原来地图基础上四周加了墙
{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,1,1},
{1,0,1,1,1,0,0,1,0,1},
{1,0,0,0,1,0,0,0,0,1},
{1,0,1,0,0,0,1,0,1,1},
{1,0,1,1,1,1,0,0,1,1},
{1,1,1,0,0,0,1,0,1,1},
{1,1,1,0,0,0,0,0,0,1},
{1,1,1,1,1,1,1,1,1,1}
};
int findway() //寻路
{
int x,y,dir;
int count=0,i=0; //记录路径数目
int find;
maze[top].x=1,maze[top].y=1,maze[top].dir=-1,top++;
map[1][1]=-1; //初始化时,将起点值改为-1,防止下面寻路又找回来,下面的路也会用到
while(top>0) //栈不空
{
x=maze[top-1].x,y=maze[top-1].y,dir=maze[top-1].dir;
if(x==endX&&y==endY) //若找到路
{
printf("\n找到第%d条路:\n",++count);
for(i=0;i<top;i++)
{
printf("(%d,%d),",maze[i].x,maze[i].y);
if((i+1)%5==0) //输出5个后换行
printf("\n");
}
if(top<minlength) //若找到的路,其长度小于已记录的路长,则最短路刷新
{
for(i=0;i<top;i++)
{
shortestPath[i]=maze[i];
}
minlength=top;
}
map[maze[top-1].x][maze[top-1].y]=0; //终点已被走过,现在重新将终点设置为可走
top--;
x=maze[top-1].x,y=maze[top-1].y,dir=maze[top-1].dir;
}
find=0;
while(dir<4&&find==0)
{
dir++;
switch(dir)
{
case 0:{x=maze[top-1].x-1,y=maze[top-1].y;}break;
case 1:{x=maze[top-1].x,y=maze[top-1].y+1;}break;
case 2:{x=maze[top-1].x+1,y=maze[top-1].y;}break;
case 3:{x=maze[top-1].x,y=maze[top-1].y-1;}break;
}
if(map[x][y]==0) //若选取的下一个方向未被访问,说明此方向可选,find置1
find=1;
}
if(find==1)
{
maze[top-1].dir=dir; //记录原来栈顶的寻路方向
maze[top].x=x,maze[top].y=y,maze[top].dir=-1; //原来栈顶选择的一个方向上元素进栈,方向记录初始化为-1
top++; //栈顶指针加1
map[x][y]=-1; //防止找路又找回来
}
else//若四个方向上都不可访问,弹出栈顶元素,对原来栈顶下一个元素进行同样的操作
{
map[maze[top-1].x][maze[top-1].y]=0;//原来栈顶元素已被走过,现在重新将其设置为可走来找其他路
top--;
}
}
return count;
}
void print_shortestPath()
{
int i=0;
printf("\n最短长度:%d,最短路径如下:\n",minlength);
for(i=0;i<minlength;i++)
{
printf("(%d,%d),",shortestPath[i].x,shortestPath[i].y);
if((i+1)%5==0)
printf("\n");
}
}
int main()
{
int havePath=findway();
if(havePath==0)
printf("此迷宫不连通\n");
else
{
print_shortestPath();
}
return 0;
}