广度优先搜索(bfs)

广度优先搜索

  • 广度优先搜索(BFS)和深度优先搜索(DFS)都是一种暴力的搜索方式,常用于解决图和树的遍历问题。

广搜概念:

广搜,即广度优先搜索(BFS),是一种在图论和树结构中常用的搜索算法。其基本思想是从起始点开始,逐层地向外扩展,以确保先探索当前层的所有节点,然后再探索下一层的节点。广搜的特点是系统地展开并检查图中的所有节点,直到找到结果为止,不考虑结果的可能位置。

  • bfs看起来像是“并行运行”,不过在程序运行时是单机运行顺序,所以可以看作是在模拟并行计算。
  • 一般在编写时,会用队列来进行具体的BFS的实现。
  • BFS实现树示意图:FBGADICEH(默认优先遍历左子树)

在这里插入图片描述

  • BFS在图中的实现(以从mark开始为例)mark-(alice-rob)-(bob-maria) 逐层遍历
    在这里插入图片描述

例题分析

(解决图问题)
在这里插入图片描述

/*题目介绍:有一个长方形的房间,在红黑砖上上下左右移动,但不能到红砖上。计算他能到达的黑砖数。
输入:第一行w,h表示房间大小。.表示黑砖,#表示红砖。@表示黑砖上的人。
输出。这个人能到达的瓷砖数。
*/
/*
使用bfs思想解题,将放入一个队列,从上将能放入的依次放入队列中,在一点点,前进输出。
*/
#include<bits/stdc++.h>
using namespace std;
char room[23][23];
int dir[4][2]={
    {-1,0},{0,-1},{1,0},{0,1}
};//定义方向数组
int wx,hy,num;
#define check(x, y) (x<wx && x>=0 && y>=0 && y<hy)//检查有没有走出房间
struct node{int x,y;};
void bfs(int dx,int dy){
    num=1;queue<node>q;
    node start,next;
    start.x=dx; start.y=dy;
    q.push(start);//将初始点位放入队列中
    while(!q.empty()){//以队列是否为空作为结束标准
        start=q.front();//将开始点位为队列中的首元素
        q.pop();//首元素出队
        //cout<<"out"<<start.x<<start.y<<endl; //打印队列元素进行验证
        for(int i=0;i<4;i++){
            next.x=start.x+dir[i][0];
            next.y=start.y+dir[i][1];
            if(check(next.x,next.y)&&room[next.x][next.y]=='.'){//当能再下去时标记砖块
                room[next.x][next.y]='#';//标记已经来过这块砖
                num++;//表示移动加一
                q.push(next);//将移动后的转放入队列,同层之后向下搜索
             }
        }
    }
}
int main(){
    int x,y,dx,dy;
    while(cin>>wx>>hy){
        if(wx==0&&hy==0)break;
        for(y=0;y<hy;y++){
            for(x=0;x<wx;x++){
                cin>>room[x][y];
                if(room[x][y]=='@'){
                    dx=x;dy=y;
                }
            }
        }
        num=0;
        bfs(dx,dy);
        cout<<num<<endl;
    }
    return 0;
}

经典例题

奇怪的电梯
在这里插入图片描述

#include <bits/stdc++.h>
using namespace std;
struct Node {
    int floor;//楼层
    int presses;//按键次数
};
int bfs(int n, int a, int b, vector<int>& k) {
    queue<Node> q;//创建一个队
    vector<bool> visited(n + 1, false);//创建一个数组存放是否到过该楼层
    q.push({a, 0});visited[a] = true;//其实楼层入队
    // BFS算法
    while (!q.empty()) {//一般套路,当队列数为0时
        Node current = q.front();//记录下当前节点为队列的头结点
        q.pop();//将当前节点出队
        int currentFloor = current.floor;//定义当前楼层和按键次数的变量
        int currentPresses = current.presses;
        // 如果到达目标楼层,返回按键次数
        if (currentFloor == b) {
            return currentPresses;
        }
        // 计算可以到达的楼层,上不超顶,下不过地
        int upFloor = currentFloor + k[currentFloor - 1];
        int downFloor = currentFloor - k[currentFloor - 1];
        // 如果上升后的楼层合法且未访问过,入队
        if (upFloor <= n && !visited[upFloor]) {
            q.push({upFloor, currentPresses + 1});
            visited[upFloor] = true;
        }
        // 如果下降后的楼层合法且未访问过,入队
        if (downFloor > 0 && !visited[downFloor]) {
            q.push({downFloor, currentPresses + 1});
            visited[downFloor] = true;
        }
    }
    // 如果无法到达目标楼层,返回-1
    return -1;
}

int main() {
    int n, a, b;
    cin >> n >> a >> b;
    vector<int> k(n);
    for (int i = 0; i < n; ++i) {
        cin >> k[i];
    }
    // 调用BFS函数并输出结果
    cout << bfs(n, a, b, k) << endl;
    
    return 0;
}

总结

总体而言其实广搜其实很好理解,代码形成也比较模式化,但还是要多练习,明白其实的搜索函数的精髓。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值