广度优先搜索理论基础
广搜(bfs)是一圈一圈的搜索过程。因为广搜是从起点出发,以起始点为中心一圈一圈进行搜索,一旦遇到终点,记录之前走过的节点就是一条最短路。
广搜的过程:我们从图中可以看出,从start起点开始,是一圈一圈,向外搜索,方格编号1为第一步遍历的节点,方格编号2为第二步遍历的节点,第四步的时候我们找到终止点end。
正是因为BFS一圈一圈的遍历方式,所以一旦遇到终止点,那么一定是一条最短路径。
代码框架:
其实,我们仅仅需要一个容器,能保存我们要遍历过的元素就可以,那么用队列,还是用栈,甚至用数组,都是可以的。
用队列的话,就是保证每一圈都是一个方向去转,例如统一顺时针或者逆时针。
因为队列是先进先出,加入元素和弹出元素的顺序是没有改变的。
cpp
#include <bits/stdc++.h>
using namespace std;
int dir[4][2] = {0, 1, 1, 0, -1, 0, 0, -1};
void bfs(vector<vector<int>>& grid, vector<vector<bool>>& visited, int x, int y){
queue<pair<int, int>> que;
que.push({})//起始节点加入队列
visited[x][y] = true;
while(!que.empty()){
pair<int, int> cur = que.front();
que.pop();
int curx = cur.first();
int cury = cur.second();
for(int i=0; i<4; i++){
int nextx = curx + dir[i][0];
int nexty = cury + dir[i][1];
if(nextx<0||nextx>=grid.size()||nexty<0||nexty>=grid[0].size()) continue;
if(!visited[nextx][nexty]){ // 如果节点没被访问过
que.push({nextx, nexty}); // 队列添加该节点为下一轮要遍历的节点
visited[nextx][nexty] = true; // 只要加入队列立刻标记,避免重复访问
}
}
}
}
99. 岛屿数量:深搜版
cpp
#include <bits/stdc++.h>
using namespace std;
//N和M表示矩阵的行数和列数
int dir[4][2] = {0,1,1,0,-1,0,0,-1};
void dfs(const vector<vector<int>>& grid, vector<vector<bool>>& visited, int x, int y){
for(int i=0; i<4; i++){
int nextx = x + dir[i][0];
int nexty = y + dir[i][1];
if(nextx<0||nextx>=grid.size()||nexty<0||nexty>=grid[0].size()) continue;
if(!visited[nextx][nexty] && grid[nextx][nexty] == 1){
visited[nextx][nexty] = true;
dfs(grid, visited, nextx, nexty);
}
}
}
int main(){
int n, m;
cin>>n>>m;
vector<vector<int>> grid(n, vector<int>(m, 0));
for(int i=0; i<n; i++){
for(int j=0; j<m; j++){
cin>>grid[i][j];
}
}
vector<vector<bool>> visited(n, vector<bool>(m, false));
int result = 0;
for(int i=0; i<n; i++){
for(int j=0; j<m; j++){
if(!visited[i][j]&&grid[i][j]==1){
visited[i][j] = true;
result++;
dfs(grid, visited, i, j);
}
}
}
cout<<result<<endl;
}
99. 岛屿数量:广搜版
只要 加入队列就代表 走过,就需要标记,而不是从队列拿出来的时候再去标记走过。
如果从队列拿出节点,再去标记这个节点走过,就会发生下图所示的结果,会导致很多节点重复加入队列。
cpp
#include <bits/stdc++.h>
using namespace std;
int dir[4][2] = {0,1,1,0,-1,0,0,-1};
void bfs(const vector<vector<int>>& grid, vector<vector<bool>>& visited, int x, int y){
queue<pair<int, int>> que;
que.push({x, y});
visited[x][y] = true;
while(!que.empty()){
pair<int, int> cur = que.front();
que.pop();
int curx = cur.first;
int cury = cur.second;
for(int i=0; i<4; i++){
int nextx = curx + dir[i][0];
int nexty = cury + dir[i][1];
if(nextx<0||nextx>=grid.size()||nexty<0||nexty>=grid[0].size()) continue;
if(!visited[nextx][nexty] && grid[nextx][nexty]==1){
que.push({nextx, nexty});
visited[nextx][nexty] = true;//只要访问就要标记
}
}
}
}
int main(){
int n, m;
cin>>n>>m;
vector<vector<int>> grid(n, vector<int>(m, 0));
for(int i=0; i<n; i++){
for(int j=0; j<m; j++){
cin>>grid[i][j];
}
}
vector<vector<bool>> visited(n, vector<bool>(m, false));
int result = 0;
for(int i=0; i<n; i++){
for(int j=0; j<m; j++){
if(!visited[i][j] && grid[i][j]==1){
result++;
bfs(grid, visited, i, j);
}
}
}
cout<<result<<endl;
}