题目描述:
用一个m×n的矩阵表示迷宫,0和1分别表示迷宫中的通路和障碍。设计一个程序,对给定的迷宫,求出找到的第一条从入口到出口的通路,或得到没有通路的结论。
我们指定:
(1) 迷宫的入口为矩阵的左上角(1,1),迷宫的出口为右下角(m,n);
(2) 路径的探索顺序依次为"东南西北"(即:右下左上)。
要求:
输入:
第一行输入两个整数,空格间隔,分别表示矩阵的行数m和列数n;
接下来的连续m行,输入迷宫矩阵的信息。
输出:
求得的通路以三元组(i,j,d)的形式输出。
其中:
i,j指示迷宫的一个坐标;
d表示走到下一坐标的方向(数字1表示东,数字2表示南,数字3表示西,数字4表示北);
终点d值为0。
解析:
1.当处于迷宫的边、角时,将不再具有四个方向,如此,会增加算法难度,为解决此问题,将行列各增加两行,并将其全部设成障碍。
如下图:设置了一个6行8列的迷宫,在其外围加了一圈障碍,(1,1)为入口,(6,8)为出口(下图出了些错误,出口标记错误)。
2.若所在位置周围没有通路,就要考虑回退,因此我们在解决这道题时应采用栈。
3.我们还应该避免兜圈子,为解决这问题,必须将曾到过的位置进行标记。
下面是代码实现:
#include <stdio.h>
#include <stdlib.h>
typedef struct n
{
int i;
int j;
int f;
struct n* next;
}link;
//创建
link* init(){
link* l = (link*)malloc(sizeof(link));
l->i=0;
l->j=0;
l->f=0;
l->next=NULL;
return l;
}
link* l;
//判空操作
int isEmpty(link *l){
if(l->next==NULL)
return 1;
return 0;
}
//入栈操作 :头插法
void ru(link *l,int i,int j,int f){
link *p = (link*)malloc(sizeof(link));
p->i=i;
p->j=j;
p->f=f;
p->next=l->next;
l->next=p;
}
//出栈操作
int chu(link* l){
if(isEmpty(l))
return 0;
link* p=l->next;
l->next=l->next->next;
free(p);
return 1;
}
//算法
int VistMaze(int maze[][100],int endi,int endj,int starti,int startj, int i, int j)
{
int end = 0;//end==flag,1为已出迷宫,0为未出
maze[i][j] = 2;
if (i == endi && j == endj){
end = 1;
}
if (end != 1 && j + 1 <= endj && maze[i][j + 1] == 0){ //右
ru(l,i,j,1);
if (VistMaze(maze,endi,endj,starti,startj, i, j + 1) == 1)
return 1;
}
if (end != 1 && i + 1 <= endi && maze[i + 1][j] == 0){ //下
ru(l,i,j,2);
if (VistMaze(maze,endi,endj,starti,startj, i + 1, j) == 1)
return 1;
}
if (end != 1 && j - 1 >= startj && maze[i][j - 1] == 0){ //左
ru(l,i,j,3);
if (VistMaze(maze,endi,endj,starti,startj, i, j - 1) == 1)
return 1;
}
if (end != 1 && i - 1 >= starti && maze[i - 1][j] == 0){ //上
ru(l,i,j,4);
if (VistMaze(maze,endi,endj,starti,startj, i - 1, j) == 1)
return 1;
}
//当下一步的各个方向均为墙时,将本部设为0通路,由上一步的2去探索下一个通路
if (end != 1){
maze[i][j] = 0;
chu(l);
}
return end;
}
//输出函数
void show(link* l){
if(l->next)
show(l->next);
if(l->i)
printf("(%d,%d,%d)",l->i,l->j,l->f);
}
int main(void)
{
int i,j;
int q,w;
// link* l;
l = init();
scanf("%d %d",&i,&j);
int a[100][100];
for(q=1;q<=i;q++){
for(w=1;w<=j;w++){
scanf("%1d",&a[q][w]);//因为输入不能带空格,所以每次在输入时截取一个字符
}
}
printf("输出路径:\n");
if(VistMaze(a,i,j,1,1,1,1) == 1){
ru(l,i,j,0);//上面的if已将除最后一步以外的所有通路全部入栈,这一步将通路最后一步单独入栈
show(l);
}
}
运行截图: