蓝桥杯 走迷宫 BFS DFS

走迷宫

题目描述:

给定一个N×M 的网格迷宫 G。G 的每个格子要么是道路,要么是障碍物(道路用 1 表示,障碍物用 00表示)。

已知迷宫的入口位置为 (x1,y1),出口位置为 (x2​,y2​)。问从入口走到出口,最少要走多少个格子。

输入描述:

输入第 11 行包含两个正整数 N,M,分别表示迷宫的大小。

接下来输入一个 MN×M 的矩阵。若 Gi,j​=1 表示其为道路,否则表示其为障碍物。

最后一行输入四个整数 x1​,y1​,x2​,y2​,表示入口的位置和出口的位置。

输出描述:

输出仅一行,包含一个整数表示答案。

若无法从入口到出口,则输出 -1。

输入样例:
5 5 
1 0 1 1 0
1 1 0 1 1 
0 1 0 1 1
1 1 1 1 1
1 0 0 0 1
1 1 5 5 
输出样例:
8
DFS代码(复杂度较高)
//dfs()
#include <iostream>
#define INF 99999999
int a[101][101],vis[101][101]={0};//a储存地图  vis标记走没走过 
int n,m,startx,starty,endx,endy,minCount=INF;
int nextSpot[4][2]={{0,1},{0,-1},{1,0},{-1,0}};//方向数组 
void dfs(int x,int y,int count) {//维护横纵坐标和当前步数 
	if (count>=minCount) return;//当前步数大于到终点的最小步数就直接结束 
	if (x==endx&&y==endy) {//到达终点 
		minCount=minCount<count?minCount:count;//更新最小步数 
		return;
	}
	for (int i=0;i<4;i++) {//循环方向数组 
		int nextx=x+nextSpot[i][0];//计算下一步的坐标 
		int nexty=y+nextSpot[i][1];
		if (nextx<=0||nexty<=0||nextx>n||nexty>m) continue;//坐标越界直接结束本循环 
		if (a[nextx][nexty]==1&&vis[nextx][nexty]==0) {//如果该坐标的值是 1(可走)并且没走过 
			vis[nextx][nexty]=1;//标记走过 
			dfs(nextx,nexty,count+1);//深搜下一步,步数加一 
			vis[nextx][nexty]=0;//深搜完取消标记 
		}
	}
}
int main() {
	cin>>n>>m;
	for (int i=1;i<=n;i++) {
		for (int j=1;j<=m;j++) {
			cin>>a[i][j];
		}
	}
	cin>>startx>>starty>>endx>>endy;
	dfs(startx,starty,0);//刚开始步数为零 
	if (minCount==INF) cout<<-1;//没路 
	else cout<<minCount;
	return 0;
}
BFS代码(可以AC)
//bfs()
#include <iostream>
#include <queue>
using namespace std;
struct place {
	int x;//横坐标 
	int y;//纵坐标 
	int count;//到达该节点走过的最小步数 
};
int main() {
	int a[101][101],vis[101][101]={0};//a储存地图  vis标记走没走过 
	int nextSpot[4][2]={{0,1},{0,-1},{1,0},{-1,0}};//方向数组 
	int n,m,startx,starty,endx,endy;
	cin>>n>>m;
	for (int i=1;i<=n;i++) {
		for (int j=1;j<=m;j++) {
			cin>>a[i][j];
		}
	}
	cin>>startx>>starty>>endx>>endy;
	queue<struct place> que;//定义队列 
	struct place temp;
	temp.x=startx;
	temp.y=starty;
	temp.count=0;
	que.push(temp);//将初始坐标放入队列 
	while (!que.empty()) {//队列为空,停止扩展 
		struct place nextPlace,front=que.front();//nextPlace:下一坐标,front:当前栈顶元素 
		for (int i=0;i<4;i++) {//循环方向数组 
			nextPlace.x=front.x+nextSpot[i][0];//计算下一步的坐标 
			nextPlace.y=front.y+nextSpot[i][1];
			nextPlace.count=front.count+1;
			if (nextPlace.x<=0||nextPlace.y<=0||nextPlace.x>n||nextPlace.y>m) continue;//坐标越界直接结束本循环 
			if (vis[nextPlace.x][nextPlace.y]==1||a[nextPlace.x][nextPlace.y]==0) continue;//如果该坐标的值是 0(不可走)或者走过就结束本次循环 
			if (nextPlace.x==endx&&nextPlace.y==endy) {//走到终点 
				cout<<nextPlace.count;
				return 0;//因为深搜特性,第一次找到的是最优解,直接结束程序即可 
			}
			que.push(nextPlace);//不是终点就加入队列,等待下一次被扩展 
			vis[nextPlace.x][nextPlace.y]=1;//标记本坐标已经被扩展 
		}
		que.pop();//队头被扩展完,则出队 
	}
	cout<<-1;//没找到终点 
	return 0;
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值