BFS 相对 DFS 的最主要的区别是:BFS 找到的路径一定是最短的,但代价就是空间复杂度可能比 DFS 大很多

常用于

  • 在一幅「图」中找到从起点 start 到终点 target 的最近距离
  • 比如说两个单词,要求你通过某些替换,把其中一个变成另一个,每次只能替换一个字符,最少要替换几次
  • 比如说连连看游戏,两个方块消除的条件不仅仅是图案相同,还得保证两个方块之间的最短连线不能多于两个拐点。你玩连连看,点击两个坐标,游戏是如何判断它俩的最短连线有几个拐点的?

    code

    ```cpp // 计算从起点 start 到终点 target 的最近距离 int BFS(Node start, Node target) { Queue q; // 核心数据结构 Set visited; // 避免走回头路

    q.offer(start); // 将起点加入队列 visited.add(start); int step = 0; // 记录扩散的步数

    while (q not empty) {

    1. int sz = q.size();
    2. /* 将当前队列中的所有节点向四周扩散 */
    3. for (int i = 0; i < sz; i++) {
    4. Node cur = q.poll();
    5. /* 划重点:这里判断是否到达终点 */
    6. if (cur is target)
    7. return step;
    8. /* 将 cur 的相邻节点加入队列 */
    9. for (Node x : cur.adj())
    10. if (x not in visited) {
    11. q.offer(x);
    12. visited.add(x);
    13. }
    14. }
    15. /* 划重点:更新步数在这里 */
    16. step++;

    } }

  1. <a name="el3Oz"></a>
  2. # 原理
  3. BFS 的逻辑,depth 每增加一次,队列中的所有节点都向前迈一步,这保证了第一次到达终点的时候,走的步数是最少的<br />DFS 实际上是靠递归的堆栈记录走过的路径,要找到最短路径,肯定得把二叉树中所有树杈都探索完才能对比出最短的路径有多长——所以时间复杂度会很高<br />而 BFS 借助队列做到一次一步「齐头并进」,是可以在不遍历完整棵树的条件下找到最短距离的。
  4. > 形象点说,DFS 是线,BFS 是面;DFS 是单打独斗,BFS 是集体行动。这个应该比较容易理解吧。
  5. <a name="L6mM7"></a>
  6. # 来点题目
  7. <a name="i6J2U"></a>
  8. ## [leetcode [111. 二叉树的最小深度]C++|BFS](https://leetcode-cn.com/problems/minimum-depth-of-binary-tree/solution/111-er-cha-shu-de-zui-xiao-shen-du-cbfs-6mtbr/)
  9. <a name="Owi6F"></a>
  10. ## L2-031 深入虎穴 (25 分)
  11. [https://pintia.cn/problem-sets/994805046380707840/problems/1111914599412858888](https://pintia.cn/problem-sets/994805046380707840/problems/1111914599412858888)
  12. ```cpp
  13. #include<bits/stdc++.h>
  14. using namespace std;
  15. #define ll long long
  16. #define FOR(i,n,m) for(int i =n;i<m;++i)
  17. const int N = 100010;
  18. bool vis[N];
  19. int n, k, d;
  20. vector<int> edge[N];//存边
  21. queue<int> q;//BFS要用
  22. int main()
  23. {
  24. ios::sync_with_stdio(false);
  25. cin>>n;
  26. FOR(i,1,n+1){
  27. cin>>k;
  28. while(k--){
  29. cin>>d;
  30. //无向边,所以两边都要加上
  31. edge[i].push_back(d);
  32. edge[d].push_back(i);
  33. }
  34. }
  35. q.push(1);//从第一个编号开始
  36. vis[1]=1;
  37. int one;
  38. while(!q.empty()){
  39. one = q.front();
  40. q.pop();
  41. for(auto v:edge[one]){//遍历该点能到的点
  42. if(vis[v])continue;//访问过就跳过
  43. vis[v] = 1;//记得记录
  44. q.push(v);
  45. }
  46. }
  47. cout<<one;//记录的队列中的最后一个 就是离入口最远的点。
  48. return 0;
  49. }

L3-004 肿瘤诊断 (30 分) | 三维地图

三维的广度优先搜索:XYZ三个数组判断方向,
对每一个点广度优先累计肿瘤块的大小,如果大于等于t就把结果累加。
用visit数组标记当前的点有没有被访问过,被访问过的结点是不会再访问的。
judge判断是否超过了边界,或者是否当前结点为0不是肿瘤

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. #define ll long long
  4. #define FOR(i,n,m) for(int i =n;i<m;++i)
  5. struct node{
  6. int x, y, z;
  7. };
  8. int m, n, l, t;
  9. //方向选择
  10. int X[6] = {1, 0, 0, -1, 0, 0};
  11. int Y[6] = {0, 1, 0, 0, -1, 0};
  12. int Z[6] = {0, 0, 1, 0, 0, -1};
  13. int arr[1300][130][80];//地图
  14. bool vis[1300][130][80];//标记
  15. //判断:过滤越界|已经标记过|是0 情况
  16. bool judge(int x, int y, int z){
  17. if(x < 0 || x >= m || y < 0 || y >= n ||
  18. z < 0 || z >= l) return false;
  19. if(arr[x][y][z] == 0 || vis[x][y][z] == 1) return false;
  20. return true;
  21. }
  22. //广搜
  23. int bfs(int x, int y, int z){
  24. int cnt = 0;//这个连通块的大小
  25. node tmp={x, y, z};
  26. queue<node> q;
  27. q.push(tmp);
  28. vis[x][y][z] = 1;//标记
  29. while(!q.empty()){
  30. node top = q.front();
  31. q.pop();
  32. cnt++;//
  33. for(int i = 0; i<6;i++){
  34. //六个方向查找
  35. int tx = top.x + X[i],
  36. ty = top.y + Y[i],
  37. tz = top.z + Z[i];
  38. if(judge(tx, ty, tz)){
  39. vis[tx][ty][tz] = 1;
  40. node tmp2={tx, ty, tz};
  41. q.push(tmp2);
  42. }
  43. }
  44. }
  45. if(cnt >= t)return cnt; //够大
  46. else return 0;
  47. }
  48. int main()
  49. {
  50. ios::sync_with_stdio(false);
  51. cin>>m>>n>>l>>t;
  52. FOR(i,0,l)
  53. FOR(j,0,m)
  54. FOR(k,0,n)
  55. cin>>arr[j][k][i];
  56. int ans = 0;
  57. FOR(i,0,l)
  58. FOR(j,0,m)
  59. FOR(k,0,n)
  60. if(arr[j][k][i] == 1 && !vis[j][k][i])
  61. ans += bfs(j,k,i);
  62. cout<<ans;
  63. return 0;
  64. }