注意:
在二维数组中没有坐标表示法,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;
}