7-1 迷宫寻路--队列

给定一个M行N列的迷宫图,其中 "0"表示可通路,"1"表示障碍物,无法通行。在迷宫中只允许在水平或上下四个方向的通路上行走,走过的位置不能重复走。

5行8列的迷宫如下:

0 1 1 1 0 0 0 0
0 0 0 1 0 0 0 0
0 1 0 0 0 1 0 0
0 1 1 1 0 1 1 0
1 0 0 0 0 0 0 0

则从左上角(1,1)至右下角(5,8)的最短路径为:

1,1--》2,1--》2,2--》2,3--》3,3--》3,4--》3,5--》4,5--》5,5--》5,6--》5,7--》5,8

题目保证每个迷宫最多只有一条最短路径。

请输出该条最短路径,如果不存在任何通路,则输出"NO FOUND".

输入格式:

第一行,输入M和N值,表示迷宫行数和列数。

接着输入M行数值,其中,0表示通路,1表示障碍物。每列数值用空格符间隔。

接下来可能输入多组迷宫数据。

当输入M的值为-1时结束输入。

输出格式:

按行顺序输出路径的每个位置的行数和列数,如 x,y

如果不存在任何路径,则输出"NO FOUND".

每组迷宫寻路结果用换行符间隔。

输入样例:

在这里给出一组迷宫。例如:

8 8    
0 0 1 0 0 0 1 0
0 0 1 0 0 0 1 0
0 0 0 0 1 1 0 0
0 1 1 1 0 0 0 0
0 0 0 1 0 0 0 0
0 1 0 0 0 1 0 0
0 1 1 1 0 1 1 0
1 0 0 0 0 0 0 0
4 4    
0 0 1 0
0 0 0 0
0 0 1 1 
0 1 0 0
-1 -1

输出样例:

在这里给出相应的输出。例如:

1,1
2,1
3,1
4,1
5,1
5,2
5,3
6,3
6,4
6,5
7,5
8,5
8,6
8,7
8,8

NO FOUND

一些思考:

①知道迷宫寻路的走路思路:
其解法的核心思想非常简单:右手原理。
从起点出发一直往里走,遇到岔路口就做一个节点记录,然后利用右手原理,一直优先选择右边的路线。
只要还能往里走,继续推进前行,直到走不下去碰壁为止,于是沿着路线返回最近的上一个节点,
选择还没有被探索过的路线进行探索,直到所有的可能性都被探索到为止。

②队列包含的数据有哪些,初始化,满的情况判断好

③存迷宫数据要用动态分配空间的二维数组,便于传入函数中。

④队头顺序输出

代码演示:

#include<stdio.h>
#include<stdlib.h>
typedef struct{
	int x,y;
	int right,down;
}position;
typedef struct{
	position *p;
	int rear,front;
}SqQueue;
/*下面/**/为如果用入队函数的表示
void EnQueue(SqQueue *Q,int s1,int s2){
	Q->p[Q->front].x = s1;
	Q->p[Q->front].y = s2;
	Q->p[Q->front].down = Q->p[Q->front].right = 1;
	Q->front++;
}
*/
int progress(SqQueue *Q,int **a,int m,int n){
	int cur_x = Q->p[Q->front-1].x; // 当前所处x的位置 
	int cur_y = Q->p[Q->front-1].y;
	int cur_r = Q->p[Q->front-1].right;//当前能走的方向情况 
	int cur_d = Q->p[Q->front-1].down;
	if(cur_r!=0 && cur_y!= n && a[cur_x][cur_y+1] == 0){//右边没走过且能走 
		Q->p[Q->front].x = cur_x;
		Q->p[Q->front].y = cur_y+1;
		Q->p[Q->front].down = Q->p[Q->front].right = 1;
		Q->p[Q->front-1].right = 0;
		Q->front++;
        /*上述五步如果用入队函数上述可改写为	
        EnQueue(&(*Q),cur_x,cur_y+1);
		Q->p[Q->front-2].right = 0;
        */
		return 1;
	}else if(cur_d!=0&& cur_x!=m && a[cur_x+1][cur_y]==0){//下面没走过且能走 
		Q->p[Q->front].x = cur_x+1;
		Q->p[Q->front].y = cur_y;
		Q->p[Q->front].down = Q->p[Q->front].right = 1;
		Q->p[Q->front-1].down = 0;
		Q->front++;
        /*上述五步如果用入队函数上述可改写为
        EnQueue(&(*Q),cur_x+1,cur_y);
		Q->p[Q->front-2].down = 0;
        */
		return 1;
	}else if(Q->front!=1){//右下都不能走且队列没有退到只剩起点,可以退回。 
		Q->front--;
		return 1;
	}
	return 0;	
}
void print(SqQueue *Q){
	while(Q->rear!=Q->front){
		int cur_x = Q->p[Q->rear].x;
		int cur_y = Q->p[Q->rear].y;
		printf("%d,%d\n",cur_x,cur_y);
		Q->rear++;
	}
}
int main()
{
	//定义两个变量m,n
	int m,n; 
	scanf("%d%d",&m,&n);
	
	while(m!=-1&&n!=-1){ // 外部循环 
		int **a = (int**)malloc(sizeof(int*)*(m+1));
		for(int i = 1;i<=m;i++){
			a[i] = (int *)malloc(sizeof(int)*(n+1));
		}//不用0行0列 
		
		for(int i = 1;i<=m;i++){
			for(int j = 1;j<=n;j++)
				scanf("%d",&a[i][j]); 
		}//存迷宫数据 
		SqQueue Q;
		Q.p = (position*)malloc(sizeof(position)*(m+n-1));//队列长度最长15 
		Q.rear = Q.front = 0; 
        
		Q.p[Q.front].x = Q.p[Q.front].y = 1;//存起始位置 
		Q.front++;
		Q.p[0].down = Q.p[0].right = 1;//1表示还没走过的方向 
        /*如果用入队函数,上述三步可写为
        EnQueue(&Q,1,1);
        */
		
		
		int flag = 1;
		while(Q.front!=m+n-1){//还没满。 
			int re = progress(&Q,a,m,n);//当前队列怎么走函数。 
			if(re == 0){
				flag = 0;
				break;
			}
		}//while走迷宫	
	
		if(flag == 0)printf("NO FOUND\n");
		else{
			print(&Q);
		}
		
		free(a);
		free(Q.p);
		scanf("%d %d",&m,&n);	
			
	}//while
	 
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值