- 常用于
- code
- L3-004 肿瘤诊断 (30 分) | 三维地图">L3-004 肿瘤诊断 (30 分) | 三维地图
- L3-004 肿瘤诊断 (30 分) | 三维地图">L3-004 肿瘤诊断 (30 分) | 三维地图
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) {
int sz = q.size();/* 将当前队列中的所有节点向四周扩散 */for (int i = 0; i < sz; i++) {Node cur = q.poll();/* 划重点:这里判断是否到达终点 */if (cur is target)return step;/* 将 cur 的相邻节点加入队列 */for (Node x : cur.adj())if (x not in visited) {q.offer(x);visited.add(x);}}/* 划重点:更新步数在这里 */step++;
} }
<a name="el3Oz"></a># 原理BFS 的逻辑,depth 每增加一次,队列中的所有节点都向前迈一步,这保证了第一次到达终点的时候,走的步数是最少的<br />DFS 实际上是靠递归的堆栈记录走过的路径,要找到最短路径,肯定得把二叉树中所有树杈都探索完才能对比出最短的路径有多长——所以时间复杂度会很高<br />而 BFS 借助队列做到一次一步「齐头并进」,是可以在不遍历完整棵树的条件下找到最短距离的。> 形象点说,DFS 是线,BFS 是面;DFS 是单打独斗,BFS 是集体行动。这个应该比较容易理解吧。<a name="L6mM7"></a># 来点题目<a name="i6J2U"></a>## [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/)<a name="Owi6F"></a>## L2-031 深入虎穴 (25 分)[https://pintia.cn/problem-sets/994805046380707840/problems/1111914599412858888](https://pintia.cn/problem-sets/994805046380707840/problems/1111914599412858888)```cpp#include<bits/stdc++.h>using namespace std;#define ll long long#define FOR(i,n,m) for(int i =n;i<m;++i)const int N = 100010;bool vis[N];int n, k, d;vector<int> edge[N];//存边queue<int> q;//BFS要用int main(){ios::sync_with_stdio(false);cin>>n;FOR(i,1,n+1){cin>>k;while(k--){cin>>d;//无向边,所以两边都要加上edge[i].push_back(d);edge[d].push_back(i);}}q.push(1);//从第一个编号开始vis[1]=1;int one;while(!q.empty()){one = q.front();q.pop();for(auto v:edge[one]){//遍历该点能到的点if(vis[v])continue;//访问过就跳过vis[v] = 1;//记得记录q.push(v);}}cout<<one;//记录的队列中的最后一个 就是离入口最远的点。return 0;}
L3-004 肿瘤诊断 (30 分) | 三维地图
三维的广度优先搜索:XYZ三个数组判断方向,
对每一个点广度优先累计肿瘤块的大小,如果大于等于t就把结果累加。
用visit数组标记当前的点有没有被访问过,被访问过的结点是不会再访问的。
judge判断是否超过了边界,或者是否当前结点为0不是肿瘤
#include<bits/stdc++.h>using namespace std;#define ll long long#define FOR(i,n,m) for(int i =n;i<m;++i)struct node{int x, y, z;};int m, n, l, t;//方向选择int X[6] = {1, 0, 0, -1, 0, 0};int Y[6] = {0, 1, 0, 0, -1, 0};int Z[6] = {0, 0, 1, 0, 0, -1};int arr[1300][130][80];//地图bool vis[1300][130][80];//标记//判断:过滤越界|已经标记过|是0 情况bool judge(int x, int y, int z){if(x < 0 || x >= m || y < 0 || y >= n ||z < 0 || z >= l) return false;if(arr[x][y][z] == 0 || vis[x][y][z] == 1) return false;return true;}//广搜int bfs(int x, int y, int z){int cnt = 0;//这个连通块的大小node tmp={x, y, z};queue<node> q;q.push(tmp);vis[x][y][z] = 1;//标记while(!q.empty()){node top = q.front();q.pop();cnt++;//for(int i = 0; i<6;i++){//六个方向查找int tx = top.x + X[i],ty = top.y + Y[i],tz = top.z + Z[i];if(judge(tx, ty, tz)){vis[tx][ty][tz] = 1;node tmp2={tx, ty, tz};q.push(tmp2);}}}if(cnt >= t)return cnt; //够大else return 0;}int main(){ios::sync_with_stdio(false);cin>>m>>n>>l>>t;FOR(i,0,l)FOR(j,0,m)FOR(k,0,n)cin>>arr[j][k][i];int ans = 0;FOR(i,0,l)FOR(j,0,m)FOR(k,0,n)if(arr[j][k][i] == 1 && !vis[j][k][i])ans += bfs(j,k,i);cout<<ans;return 0;}
