BFS(宽度优先搜索、广度优先搜索)

宽度优先搜索算法(又称广度优先搜索)是最简便的图的搜索算法之一,这一算法也是很多重要的图的算法的原型。Dijkstra单源最短路径算法和Prim最小生成树算法都采用了和宽度优先搜索类似的思想。其别名又叫BFS,属于一种盲目搜寻法,目的是系统地展开并检查图中的所有节点,以找寻结果。换句话说,它并不考虑结果的可能位置,彻底地搜索整张图,直到找到结果为止 。

 

BFS算法常用于求最短路径或者求扩散性质的区域问题。

(1)走迷宫最短路径

(2)数字按规则转换的最少次数

(3)棋盘上某个棋子N步后能到达的位置总数

(4)病毒扩散计算

(5)图像中连通块的计算。

模板

可以分为四个步骤:初始化(初始化队列和所求的值) -> 判空取队头(判断是否为空并取出队头) -> 拓展(利用队头去扩展)->依次四个方向 -> 判断入队(如果符合,将该点入队)。

void bfs(){
	queue<int>q;
    //此处定义一个哈希map存距离或者定义全局二维数组存距离
	q.push(初始位置);
    //初始位置距离赋值0
	int dx[4]={-1,0,1,0},dy[4]={0,1,0,-1};//四个方向上的向量
	
	while(q.size()){
        auto t = q.front();
        q.pop();//取出队头的点,用该点向周围扩散。
		for(int i=0;i<4;i++){
            int a=   ,b=  
            if(check(j)){       //如果该点可行就将它加入队列中
            q.push(j);		
            //实施相应的操作 
            }
        }
	} 
} 

 

#include<bits/stdc++.h>
using namespace std;
const int N=110;
typedef pair<int ,int> PII;
int n,m;
int g[N][N];//存放地图
int d[N][N];//存放该点到起点的距离

int bfs(){
	queue<PII> q;
	memset(d, -1 ,sizeof d);//将值全部初始化为-1 代表还没有走过
	d[0][0]=0;//第一个点已经走过
	q.push({0,0});//将起点插入队列中
    int dx[4]={-1,0,1,0},dy[4]={0,1,0,-1};//四个方向上的向量
	while(q.size()){//判断队列是否为空
		auto t=q.front();//取出对头元素
		q.pop();//弹出队头元素
		for(int i=0;i<4;i++){
			int x=t.first+dx[i],y=t.second+dy[i];
			if(x>=0&&x<n&&y>=0&&y<m&&g[x][y]==0&&d[x][y]==-1){//x、y符合条件 该位置为0 且没有走过
				d[x][y]=d[t.first][t.second]+1;//离起点距离加 1
				q.push({x,y});//坐标入队
			}
		}
	}
	return d[n-1][m-1];
}
int main(){
	cin>>n>>m;
	for(int i=0;i<n;i++)
		for(int j=0;j<m;j++)
		cin>>g[i][j];
	cout<<bfs()<<endl;
	return 0;
}

👉 解析点这👈

#include<bits/stdc++.h>
using namespace std;

int bfs(string start) {
	string end="12345678x";//完成时的字符串
	queue<string> q;
	unordered_map<string,int > d; //存放某个字符串到起点的距离
	q.push(start);//将字符串插入队列
	d[start]=0;//到起点的距离为0
	int dx[4]={-1,0,1,0},dy[4]={0,1,0,-1};//四个方向上的向量
	while(q.size()){//对列不为空
		auto t=q.front();
		q.pop();//弹出对头
		int distance=d[t];
		if(t==end) return distance;//相等则返回距离
		//一维数组转化为二维数组的技巧
		int k=t.find('x');//查找x所在的下标
		int x=k/3,y=k%3;//转化为2维数组时的下标
		for(int i=0;i<4;i++){
			int a=x+dx[i],b=y+dy[i];
			if(a>=0&&a<3&&b>=0&&b<3){//如果a,b没有越界
				swap(t[k],t[a*3+b]);//把x和要走的位置 互换一下
				if(!d.count(t)){//如果当前位置没有走过  每次四个方向判断完后都被弹出了  下次再走时已经不存在
					d[t]=distance+1;
					q.push(t);
				}
				swap(t[k],t[a*3+b]);//把位置还原 继续判断下一个方向
			}
		}
	}
	return -1;
}
int main() {
	char c;
	string start;
	for(int i=0; i<9; i++) {
		cin>>c;
		start+=c;//字符的拼接
	}
	cout<<bfs(start)<<endl;
	return 0;
}

套模板是如此的简单 直接上代码 

#include<bits/stdc++.h>
using namespace std;
const int N=110;
typedef pair<int,int> PII;
int g[N][N];
int d[N][N];
int n,m;
int x3,y3,x2,y2;//y0,y1与math头文件有冲突 不能用
int bfs(int x3,int y3,int x2,int y2){
    bool st=false;
    memset(d,-1,sizeof(d));
    d[x3][y3]=0;
    queue<PII> q;
    q.push({x3,y3});
    while(q.size()){
        auto t=q.front();
        if(t.first==x2&&t.second==y2) st=true;
        q.pop();
        int dx[4]={-1,0,1,0},dy[4]={0,1,0,-1};
        for(int i=0;i<4;i++){
            int x=t.first+dx[i],y=t.second+dy[i];
            if(x>=1&&x<=n&&y>=1&&y<=m&&d[x][y]==-1&&g[x][y]==1){
                d[x][y]=d[t.first][t.second]+1;
                q.push({x,y});
            }
        }
    }
   if(st) return d[x2][y2];
    return -1;
}
int main(){
    cin>>n>>m;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        cin>>g[i][j];
    cin>>x3>>y3>>x2>>y2;
    cout<<bfs(x3,y3,x2,y2)<<endl;
}

 

 也可以说是bfs吧

#include<bits/stdc++.h>
using namespace std;
const int N=1010;
char a[N][N];
char b[N][N];
int n,m,k;

void bfs(){
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        b[i][j]=a[i][j];
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            if(b[i][j]=='g'){
                if(i-1>=1)
                a[i-1][j]='g';
                if(i+1<=n)
                a[i+1][j]='g';
                if(j-1>=1)
                a[i][j-1]='g';
                if(j+1<=m)
                a[i][j+1]='g';
            }
        }
    }
}
int main(){
    cin>>n>>m;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        cin>>a[i][j];
    cin>>k;
    while(k--){
        bfs();
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            cout<<a[i][j];
        }
        cout<<endl;
    }
    return 0;
}

#include<bits/stdc++.h>
using namespace std;

string start,ed;
int len;

int bfs(){
    unordered_map <string,int>dist;
    dist[start] = 0;
    queue<string> q;
    q.push(start);
    while(q.size()){
        auto t = q.front();
        q.pop();
        int distance = dist[t];
        if(t==ed) return distance;
        int dx[6] = {1,-1,2,-2,3,-3};
        
        int k = t.find('*');
        for(int i = 0;i < 6;i++){
            int x = k + dx[i];
            if(x >= 0 && x < len){
                swap(t[k],t[x]);
                if(!dist.count(t)){
                    dist[t] = distance + 1;
                    q.push(t);
                }
                swap(t[k],t[x]);
            }
        }
    }
    return -1;
}

int main(){
    cin>>start>>ed;
    len=start.size();
    cout << bfs() << endl;
    return 0;
}

 

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值