当前位置:   article > 正文

蓝桥杯 走迷宫 BFS DFS_java给定一个 n×m 的网格迷宫 g。g 的每个格子要么是道路,要么是障碍物(道路用1

java给定一个 n×m 的网格迷宫 g。g 的每个格子要么是道路,要么是障碍物(道路用1

迷宫

题目描述:

给定一个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 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
输出样例:
8
  • 1
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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/390029?site
推荐阅读
相关标签
  

闽ICP备14008679号