迷宫问题

题目来源:https://www.dotcpp.com/oj/problem1672.html

小明置身于一个迷宫,请你帮小明找出从起点到终点的最短路程。
小明只能向上下左右四个方向移动。
输入包含多组测试数据。输入的第一行是一个整数T,表示有T组测试数据。
每组输入的第一行是两个整数N和M(1<=N,M<=100)。
接下来N行,每行输入M个字符,每个字符表示迷宫中的一个小方格。
字符的含义如下:
‘S’:起点
‘E’:终点
‘-’:空地,可以通过
‘#’:障碍,无法通过
输入数据保证有且仅有一个起点和终点。
对于每组输入,输出从起点到终点的最短路程,如果不存在从起点到终点的路,则输出-1。
样例输入:
1
5 5
S-###
-----
##---
E#---
---##
样例输出

/*	广度优先搜索双队列(QueX和QueY)分别存储横纵坐标 
	1、输入迷宫数据到二维字符型数组map 
	2、创建跟踪数组step记录每节点步数
	3、创建步伐数组
	4、用两个队列分别记录可用点的x坐标和y坐标
	5、当节点的x坐标=ex且y坐标=ey时从计步数组step返回步数,否则返回-1*/
#include<stdio.h> 
#include<string.h>
#define SIZE 100
//为了省事都扔在这里了,函数调用的时候一个指针就行了 
typedef struct MazeBFS{ 
	int QueX[SIZE*SIZE];
	int QueY[SIZE*SIZE];
	int step[SIZE][SIZE];
	char map[SIZE][SIZE]; 
	int head,tail;
	int N,M;
	int sx,sy,ex,ey;
}Maze;
void MazeInit(Maze *maz);//结构体初始化 
void InputMap(Maze *maz);//输入迷宫地图 
void InOutPoint(Maze *maz);//搜索入口和出口坐标 
void QueInit(Maze *maz);//坐标队列初始化 
int PathFinding(Maze *maz);//广度优先-搜索路径 
int main(int argc,char const *argv[]){
	Maze maz;
	int i,path,T;
	scanf("%d",&T);
	while(T--){
		MazeInit(&maz);//输入新地图之前清零存储区
		scanf("%d%d",&maz.N,&maz.M);
		InputMap(&maz);
		InOutPoint(&maz); 
		QueInit(&maz);
		path = PathFinding(&maz);
		printf("%d\n",path);
	}
	return 0;
}

//初始化结构体,所有存储单元清零 
void MazeInit(Maze *maz){
	memset((void *)maz,0,sizeof(Maze));
}

//输入N行地图数据到map 
void InputMap(Maze *maz){
	int i;
	for(i = 0;i < maz->N;i++){
		scanf("%s",maz->map[i]);
	}
}

//找到入口点(sx,sy)和出口点(ex,ey)
void InOutPoint(Maze *maz){
	int i,j;
	for(i = 0;i < maz->N;i++){
		for(j = 0;j < maz->M;j++){
			if(maz->map[i][j] == 'S'){
				maz->sx = i;
				maz->sy = j;
			}
			if(maz->map[i][j] == 'E'){
				maz->ex = i;
				maz->ey = j;
			}
		}
	}
} 

//初始化坐标队列和计数矩阵 
void QueInit(Maze *maz){
	maz->head = 0;
	maz->tail = 0;
	maz->QueX[maz->tail] = maz->sx;
	maz->QueY[maz->tail] = maz->sy;
	maz->tail++;
	maz->step[maz->sx][maz->sy] = 1;
}

//四个方向寻路
int PathFinding(Maze *maz) {
	int xp[] = {-1,1,0,0};//xp和yp通过给坐标加减一以实现移动 
	int yp[] = {0,0,-1,1};//比如xp[0]yp[0]表示i坐标减一,而j坐标不变 
	int tx,ty;
	int nx,ny;
	int i;
	while(maz->head != maz->tail){
		tx = maz->QueX[maz->head];
		ty = maz->QueY[maz->head];
		maz->head++;
		if(tx == maz->ex&&ty == maz->ey){
			return maz->step[maz->ex][maz->ey] -1;
		} 
		for(i = 0;i < 4;i++){
			nx = tx + xp[i];//-1,1,0,0 
			ny = ty + yp[i];//0,0,-1,1 
			if(nx >= 0&&nx < maz->N&&ny >= 0&&ny < maz->M&&//坐标不越界 并且 
			maz->map[nx][ny] != '#'&&maz->step[nx][ny] ==0){//该点可走并且没走过 
				maz->QueX[maz->tail] = nx; 
				maz->QueY[maz->tail] = ny;//新可用点坐标入队列 
				maz->tail++;
				maz->step[nx][ny] = maz->step[tx][ty] +1;//相应点计数器加一 
			}
		}
	}
	return -1;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值