【BFS】【入门】广度优先搜索(BFS)

注意:

在二维数组中没有坐标表示法,x就为行,y为列,具体画矩阵来理解!不要有坐标系的想法!!!

一.概念

广度优先搜索:简称bfs。从第一层开始搜索,当该层搜索完毕后,往下一层进发,开始下一层的搜索。

总结:按层遍历,找到即最优。

二.经典例题

        2.1.1悟空救我

        题目来源:童程童美

题目

“悟空,救我!”,师父发出了求救信号。“我被装在了一个由m行n列的格子组成的迷宫里,有的格子里面有机关,不能通过。我给你迷宫的入口坐标,迷宫地图以及我的坐标,以最快速度(经过的格子最少)赶来救我!”

“对了,每个格子只能向水平方向或垂直方向走,不能斜着走!切记!”

样例输入                                       

5 4
0 0 1 0
0 0 0 0
0 0 1 0
0 1 0 1
0 0 0 1
1 1 4 3

样例输出

 7

说明:

第一行:5 4代表迷宫为5行4列 。

接下来的5行代表迷宫地图,0表示空地,1表示机关障碍。

最后一行,前两个数表示入口坐标, 后两个数表示师傅坐标。

7表示要救到师傅最快需要7步。

        2.1.2思路:

此题过于经典,标准的广搜入门题,思路即深搜!

注意:由题意得地图的起始点是(1,1)而不是(0,1)

 

       

        2.1.3核心代码(具体解释见注释)

​
​
while(head<tail){
		//四个方位进行遍历 
		for(int i=0;i<4;i++){
			//存入临时坐标 
			tx=que[head].x+nt[i][0];
			ty=que[head].y+nt[i][1];
			//越界continue 
			if(tx<0 || tx>m || ty<0 || ty>n) continue;
			//判断临时坐标是否可以转正式 。条件:没走过,没障碍。 
			if(map[tx][ty]==0 &&book[tx][ty]==0){
				book[tx][ty]=1;
				que[tail].x=tx;
				que[tail].y=ty;
				que[tail].step=que[head].step+1;
				tail++;
			}
			//匹配成功就可以结束了 
			if(tx==bx &&ty==by){
				flag=1;
				break;
			}
		}
		if(flag) break;
		head++;   //没找到,进入下一层。 
	}

​

​

        2.1.4AC代码(具体解释见注释)

#include<iostream>
using namespace std;
struct shou{
	int step,x,y;
} que[2501];
int map[25][25],book[25][25];  //map为地图,book为是否遍历过 
int nt[4][2]={{-1,0},{0,1},{1,0},{0,-1}}; //四个方位 
int n,m;//地图大小 
int ax,ay;//原始位置
int bx,by;//终点 
int tx,ty;//过渡 
int head=1,tail=1,flag=0;
void fbs(){
	//赋原始值 
	que[tail].x=ax;
	que[tail].y=ay;
	que[tail].step=0;
	tail++;
	book[ax][ay]=1;   //原点已走过 
	
	while(head<tail){
		//四个方位进行遍历 
		for(int i=0;i<4;i++){
			//存入临时坐标 
			tx=que[head].x+nt[i][0];
			ty=que[head].y+nt[i][1];
			//越界continue 
			if(tx<1 || tx>m || ty<1 || ty>n) continue;
			//判断临时坐标是否可以转正式 。条件:没走过,没障碍。 
			if(map[tx][ty]==0 &&book[tx][ty]==0){
				book[tx][ty]=1;
				que[tail].x=tx;
				que[tail].y=ty;
				que[tail].step=que[head].step+1;
				tail++;    //因为这个多加了,所以最终结果中要减去1 
			}
			//匹配成功就可以结束了 
			if(tx==bx &&ty==by){
				flag=1;
				break;
			}
		}
		if(flag) break;
		head++;   //没找到,进入下一层。 
	}
}
int main(){
	cin>>m>>n;
	//输入地图 
	for(int i=0;i<m;i++){
		for(int j=0;j<n;j++){
			cin>>map[i][j];
		}
	}
	cin>>ax>>ay>>bx>>by; 
	fbs();
	cout<<que[tail-1].step<<endl;
	return 0;
}

        2.2.1畅游花果山

题目描述

“花果山旅游景区正式开放啦!”已知景区内有n (1<n<10) 个景点,每个景点之间有路。从1号景点到达n号景点要经过若千个景点。现在要找到经过景点最少的一条路线。

输入

 m+1行,每行两个整数。第一行两个整数表示景点数量n和路的数量m,后面每行两个数,表示两个景点之间有路
输出

 若干个整数,表示1-n之间最少景点的路线。

【样例输入】

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

【样例输出】

1->6->8

         2.2.2思路

1.先按照题意,把图像画出来

 2.再把它转化为树状图更加直观

         2.2.3核心代码(具体解释见注释)

void print(int n){
	if(n==1){
		cout<<que[n].city;
	}else{
		print(que[n].pre);
		cout<<"->"<<que[n].city;
	}
}
void bfs(){
	//初始化 
	que[tail].city=1;
	que[tail].pre=0;
	tail++;
	while(head<tail){
		for(int i=1;i<=n;i++){
			//找地图,看看有没有路线 
			if(map[que[head].city][i]==1 &&book[i]==0){
				que[tail].city=i;
				que[tail].pre=head;
				tail++;
				book[i]=1;
				if(que[tail-1].city==n){
					flag=1;
					print(tail-1);
					break;
				} 
			}
		}
		if(flag) break;
		head++;
	}
}

        2.2.4AC代码(具体解释见注释)

#include<iostream>
using namespace std;
int n,m;  //n表景区,m表路线 
int map[20][20],book[20];  //地图,和是否走过这个景点 
int head=1,tail=1;  //头和尾 
int flag=0;
struct node{
	int pre,city;
}que[101];
void print(int n){
	if(n==1){
		cout<<que[n].city;
	}else{
		print(que[n].pre);
		cout<<"->"<<que[n].city;
	}
}
void bfs(){
	//初始化 
	que[tail].city=1;
	que[tail].pre=0;
	tail++;
	while(head<tail){
		for(int i=1;i<=n;i++){
			//找地图,看看有没有路线 
			if(map[que[head].city][i]==1 &&book[i]==0){
				que[tail].city=i;
				que[tail].pre=head;
				tail++;
				book[i]=1;
				if(que[tail-1].city==n){
					flag=1;
					print(tail-1);
					break;
				} 
			}
		}
		if(flag) break;
		head++;
	}
}
int main(){
	cin>>n>>m;
	int a,b;
	for(int i=0;i<m;i++){
		cin>>a>>b;
		//道路是互通的 
		map[a][b]=1;
		map[b][a]=1;
	}
	book[1]=1;
	bfs();
	return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值