关于广搜(BFS)

1、

在这里插入图片描述
步骤顺序:
A先入队列,找到B和C,之后B、C入队列,A出队列;
B找到D和E,之后B出队列,C找到F和G,之后C出队列;

以此类推
<-- [A]
<-- [B] [C]
<-- [C] [D] [E]
<-- [D] [E] [F] [G]
<-- [E] [F] [G]
<-- [F] [G]
<-- [G]

2、

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

3、关于c++中的队列

BFS一般需要用到队列,所以我们必须牢记队列中的一些常用函数

#include<cstdio>
#include<iostream>
#include<queue>//使用c++的”队列“必须要导入这个头文件
using namespace std;

void queDemo()//队列
{
    
    
	int n,i;
    queue<int> q;//声明一个整数类型队列
    cin>>n;//scanf()的时间效率比cin更高,因此有大量数据输入时要用scanf()

   //往队列q中依次添加:1,2,3....n
   for(i=0;i<n;i++)
        q.push(i+1);//添加到队列q的末尾
        
   //size()函数返回队列的长度
   cout<<"队列长度:"<<q.size()<<endl;
   
   //back()函数返回:队列最后一个元素---只读,不删
   cout<<"back:"<<q.back()<<endl;
   cout<<"back:"<<q.back()<<endl;
   
   //依次输出队列中的元素(先进先出)
   while(!q.empty())//empty()函数返回队列是否为空,!--非空
   {
    
    
       //front()函数返回队列的第一个元素---只读,不删
       cout<<q.front()<<" ";
       q.pop();//pop()函数只是删除(队列的第一个元素),并不返回元素值
   }

   cout<<endl;
}

1.代码举例

摘抄自:https://blog.csdn.net/wr132/article/details/43274397

     (1)将起始节点放入队列尾部
     (2)While(队列不为空)
               取得并删除队列首节点Node

                处理该节点Node

                把Node的未处理相邻节点加入队列尾部

代码如下(示例):

#include <iostream>
#include <queue>
using namespace std;
 
//节点数 
#define M 10
 
//图的矩阵表示 
int matrix[M][M] = 
{
    
     0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 
  1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 
  0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 
  0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 
  1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 
  0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 
  0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 
  0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 
  0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 
  0, 0, 0, 0, 0, 0, 1, 1, 0, 0
 
}; 
//访问标记,初始化为0, 
int visited[M + 1];
 
//graph traverse 
void GT_BFS() 
{
    
     
visited[1] = 1; 
queue<int> q; 
q.push(1); 
while(!q.empty()) 
{
    
     
   int top = q.front(); 
   cout << top<<" ";//输出 
   q.pop(); 
   int i ; 
   for(i = 1; i <= M; ++i) 
   {
    
     
    if(visited[i] == 0 && matrix[top - 1][i - 1 ] == 1) 
    {
    
     
     visited[i] = 1; 
     q.push(i); 
    } 
   } 
} 
}
 
int main() 
{
    
     
GT_BFS();//输出结果为1 2 5 3 4 9 7 6 8 10 
//system("pause"); 
return 0; 
}

2、

https://blog.csdn.net/zjuwxx/article/details/95627952
题目详情

Description

给定一个大小为 N * M 的迷宫。迷宫由通道和墙壁组成,每一步可以向邻接的上下左右四格的通道移动。请求出从起点到终点所需的最小步数

限制条件:

N,M <= 100

扫描二维码关注公众号,回复: 13146728 查看本文章

Input

输入两个数字 N 和 M,分别表示迷宫的长和宽,用空格隔开

输入代表迷宫的字符串,N 行 M 列,由 ‘#’,’~’,‘S’,‘G’ 组成,分别表示墙壁,通道,起点,终点

Output

从起点到终点所需的最小步数

Sample Input

10 10
#S######.#
......#..#
.#.##.##.#
.#........
##.##.####
....#....#
.#######.#
....#.....
.####.###.
....#...G#

Sample Output

22
BFS的迷宫最短路径
(1)

#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
 
const int INF=100000000;
const int MAX_N=100+5,MAX_M=100+5;
typedef pair<int,int> P; //把 pair看作结构体,typedef的用法,P就是该结构体的一个实例。该"结构体"内只有两个元素 
 
//输入
char a[MAX_N][MAX_M]; //表示迷宫的字符串数组 
int N,M; //迷宫的长宽 
int sx,sy; //起点坐标 
int gx,gy; //终点坐标
int d[MAX_N][MAX_M]; //存放到各个位置的最短距离的数组
 
//向四个方向移动的向量:右、上、左、下 
int dx[4]={
    
    1,0,-1,0}; //dx[i]是向量的横坐标
int dy[4]={
    
    0,1,0,-1}; //dy[i]是向量的纵坐标
 
//从(sx,sy)到(gx,gy)的最短距离。如果无法到达,则是INF
int bfs(){
    
    
	queue<P> que;
	
	for(int i=0;i<N;++i){
    
    
		for(int j=0;j<M;++j){
    
    
			d[i][j]=INF; //把所有位置的距离初始化为INF 
		}
	}
	//将起点加入队列,并把这一地点的距离设置为0
	que.push(P(sx,sy));
	d[sx][sy]=0;
	
	//不断循环直到队列为空
	while(que.size()){
    
    
		//从队列最前端取出元素 
		P p=que.front();
		que.pop();
		//如果取出的状态已经是终点,结束搜索
		if(p.first==gx && p.second==gy){
    
    
			break;
		} 
		
		//四个方向的循环 
		for(int i=0;i<4;++i){
    
    
			//移动后的位置记为 (nx,ny)
			int nx=p.first+dx[i],ny=p.second+dy[i];
			//判断是否可以移动,是否已经访问过该点(d[nx][ny]!=INF即为访问过)
			if(0<=nx && nx<N && 0<=ny && ny<M && a[nx][ny]!='#' && d[nx][ny]==INF){
    
    
				//如果能够移动则加入队列,且到该位置的距离变成到 p 的距离 +1 
				que.push(P(nx,ny));
				d[nx][ny]=d[p.first][p.second]+1; 
			} 
		} 
	}
	return d[gx][gy];
}
 
int main(){
    
    
	scanf("%d%d",&N,&M);
	for(int i=0;i<N;++i){
    
    
		scanf("%s",a[i]);
	}
	for(int i=0;i<N;++i){
    
    
		for(int j=0;j<M;++j){
    
    
			if(a[i][j]=='S'){
    
    
				sx=i;
				sy=j;
			}
			if(a[i][j]=='G'){
    
    
				gx=i;
				gy=j;
			}
		}
	}
	int res=bfs();
	printf("%d",res);
	return 0;
}

(2)

#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;

const int INF=100000000;
const int MAX_N=100+5,MAX_M=100+5;
//typedef pair<int,int> P; //把 pair看作结构体,typedef的用法,P就是该结构体的一个实例。该"结构体"内只有两个元素
struct node{
    
    
int first;
int second;
}P;
//输入
char a[MAX_N][MAX_M]; //表示迷宫的字符串数组
int N,M; //迷宫的长宽
int sx,sy; //起点坐标
int gx,gy; //终点坐标
int d[MAX_N][MAX_M]; //存放到各个位置的最短距离的数组

//向四个方向移动的向量:右、上、左、下
int dx[4]={
    
    1,0,-1,0}; //dx[i]是向量的横坐标
int dy[4]={
    
    0,1,0,-1}; //dy[i]是向量的纵坐标

//从(sx,sy)到(gx,gy)的最短距离。如果无法到达,则是INF
int bfs(){
    
    
	queue<node> que;

	for(int i=0;i<N;++i){
    
    
		for(int j=0;j<M;++j){
    
    
			d[i][j]=INF; //把所有位置的距离初始化为INF
		}
	}
	//将起点加入队列,并把这一地点的距离设置为0
	//que.push(P(sx,sy));
	P.first=sx;
	P.second=sy;
	que.push(P);
	d[sx][sy]=0;

	//不断循环直到队列为空
	while(!que.empty()){
    
    
		//从队列最前端取出元素
		node p=que.front();
		que.pop();
		//如果取出的状态已经是终点,结束搜索
		if(p.first==gx && p.second==gy){
    
    
			break;
		}

		//四个方向的循环
		for(int i=0;i<4;++i){
    
    
			//移动后的位置记为 (nx,ny)
			int nx=p.first+dx[i],ny=p.second+dy[i];
			//判断是否可以移动,是否已经访问过该点(d[nx][ny]!=INF即为访问过)
			if(0<=nx && nx<N && 0<=ny && ny<M && a[nx][ny]!='#' && d[nx][ny]==INF){
    
    
				//如果能够移动则加入队列,且到该位置的距离变成到 p 的距离 +1
				//que.push(P(nx,ny));
				P.first=nx;
                P.second=ny;
                que.push(P);
				d[nx][ny]=d[p.first][p.second]+1;
			}
		}
	}
	return d[gx][gy];
}

int main(){
    
    
	scanf("%d%d",&N,&M);
	for(int i=0;i<N;++i){
    
    
		scanf("%s",a[i]);
	}
	for(int i=0;i<N;++i){
    
    
		for(int j=0;j<M;++j){
    
    
			if(a[i][j]=='S'){
    
    
				sx=i;
				sy=j;
			}
			if(a[i][j]=='G'){
    
    
				gx=i;
				gy=j;
			}
		}
	}
	int res=bfs();
	printf("%d",res);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/wenrenfudi/article/details/113606304