BFS一般用队列实现,且总是按层次的顺序进行的遍历,其基本写法如下:
void BFS(int s){
queue<int> q;
q.push(s);
while(!q.empty()){
取出队首元素top;
访问队首元素top;
队首元素出队;
将下一层结点中未访问过的结点全部入队,并设置成以访问;
//一般是枚举若干个方向,判断合法性,若合法刷新坐标,标记以访问,然后入队
}
}
上面需要用到:
1)坐标的描述 ( 以二维为例 )
struct node{
int x,y;
int step;//记录步数
} Node;
若想记录步数,只需在刷新坐标的同时队 对应step+1 即可
2)枚举若干方向
int X[4]={0,0,1,-1};
int Y[4]={1,-1,0,0};
3)判断坐标合法性
bool Judge(int x,int y){
if(x>=n || x<0 || y>=m || y<0) return false;
if(vis[x][y]==true || matrix[x][y]==0) return false;
return true;
}
由于每一个BFS可以访问一个联通块,
因此,若想得到联通块的个数只需在调用BFS函数后进行变量++记录即可。若想得到每一个联通块内的符合条件的的坐标的个数(比如0 1矩阵中1的个数),只需在BFS函数内部队首元素出队访问时进行变量++记录即可。
几个练习题小试牛刀:
1 :求矩阵中 “块“ 的个数(块为若干个1相邻)
输入数据:
6 7
0 1 1 1 0 0 1
0 0 1 0 0 0 0
0 0 0 0 1 0 0
0 0 0 1 1 1 0
1 1 1 0 1 0 0
1 1 1 1 0 0 0
输出数据
4
完整代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn=1010;
struct node{
int x,y;
} Node;
int m,n;
int matrix[maxn][maxn];
bool vis[maxn][maxn];
//枚举四个方向;
int X[4]={0,0,1,-1};
int Y[4]={1,-1,0,0};
bool Judge(int x,int y){
if(x>=n || x<0 || y>=m || y<0) return false;
if(vis[x][y]==true || matrix[x][y]==0) return false;
return true;
}
void BFS(int x,int y){
queue<node> q;
Node.x =x,Node.y =y; //当前坐标
q.push(Node);
vis[x][y]=true; //设置(x,y)已入队过
while(!q.empty()){
node now=q.front();
q.pop();
//枚举四个方向
for(int i=0;i<4;i++){
int NewX=now.x +X[i];
int NewY=now.y +Y[i];
if(Judge(NewX,NewY)){ //
Node.x =NewX;
Node.y =NewY;
vis[NewX][NewY]=true;
q.push(Node);
}
}
}
}
int main(){
cin>>n>>m;
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
cin>>matrix[i][j];
}
}
int ans=0;//存块数
//枚举每一个位置;
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
if(matrix[i][j]==1 && vis[i][j]==false){
BFS(i,j);
ans++;
}
}
}
cout<<ans<<endl;
return 0;
}
2 :求走迷宫的最小步数
由S到达T的最小步数,' * '代表墙,不可穿过,‘ . ’ 可以走
输入数据:
5 5
.....
.*.*.
.*S*.
.***.
...T*
2 2 4 3
输出数据:
11
思路:个上一道题类似,只是在BFS搜索中添加了步数,也就是结构体node里添加了step记录步数而已,对上述代码进行简单修改即可。
完整代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn=1010;
struct node{
int x,y;
int step;
} S,T,Node;
int m,n;
char matrix[maxn][maxn];
bool vis[maxn][maxn];
//枚举四个方向;
int X[4]={0,0,1,-1};
int Y[4]={1,-1,0,0};
bool Judge(int x,int y){
if(x>=n || x<0 || y>=m || y<0) return false;
if(vis[x][y]==true || matrix[x][y]=='*') return false;
return true;
}
int BFS(int x,int y){
queue<node> q;
q.push(S);
vis[x][y]=true; //设置(x,y)已入队过
while(!q.empty()){
node now=q.front();
q.pop();
if(now.x == T.x && now.y == T.y ){ //起点是终点
return now.step ;
}
//枚举四个方向
for(int i=0;i<4;i++){
int NewX=now.x +X[i];
int NewY=now.y +Y[i];
if(Judge(NewX,NewY)){ //
Node.x =NewX;
Node.y =NewY;
Node.step =now.step +1;
vis[NewX][NewY]=true;
q.push(Node);
}
}
}
return -1;
}
int main(){
cin>>n>>m;
for(int i=0;i<n;i++){
getchar();// 过滤换行符
for(int j=0;j<m;j++){
cin>>matrix[i][j];
}
}
cin>>S.x >>S.y >>T.x >>T.y ;
cout<<BFS(S.x,S.y)<<endl;
return 0;
}
3:1091 Acute Stroke (30 point(s))
这道题也是个典型的BFS搜索,不过是三维的:
注意点:1) 数据读入时先读入第三维(切片的个数),再读入每一片(测试样例也很容易看到)
2)在访问每一块中记录1的个数(每访问一个块,返回一个块内1的个数)
根据前面的模板,很容易写出代码:
完整代码:
#include<bits/stdc++.h>
using namespace std;
struct node{
int x,y,z;
} Node;
int m,n,l,t;
int matrix[1300][130][80];
bool vis[1300][130][80];
//枚举八个方向;
int X[6]={1,-1,0,0,0,0};
int Y[6]={0,0,1,-1,0,0};
int Z[6]={0,0,0,0,1,-1};
bool Judge(int x,int y,int z){
if(x>=n || x<0 || y>=m || y<0 || z>=l || z<0) return false;
if(vis[x][y][z]==true || matrix[x][y][z]==0) return false;
return true;
}
int BFS(int x,int y,int z){
queue<node> q;
Node.x =x; //当前坐标
Node.y =y;
Node.z =z;
int cnt=0; //记录联通块中 1 的个数
q.push(Node);
vis[x][y][z]=true; //设置(x,y)已入队过
while(!q.empty()){
node now=q.front();
q.pop();
cnt++;//当前块中1的个数 +1
for(int i=0;i<6;i++){
int NewX=now.x +X[i];
int NewY=now.y +Y[i];
int NewZ=now.z +Z[i];
if(Judge(NewX,NewY,NewZ)){ //
Node.x =NewX;
Node.y =NewY;
Node.z =NewZ;
vis[NewX][NewY][NewZ]=true;
q.push(Node);
}
}
}
if(cnt>=t) return cnt; //如果超过阈值,即这个联通块中 1 的个数不小于 t 才算数。
else return 0;
}
int main(){
cin>>n>>m>>l>>t;
for(int z=0;z<l;z++){ //先输入层数,即第三维
for(int x=0;x<n;x++){
for(int y=0;y<m;y++){
cin>>matrix[x][y][z]; //注意数据读入
}
}
}
int ans=0;
//枚举每一个位置;
for(int z=0;z<l;z++){ //先输入层数,即第三维
for(int x=0;x<n;x++){
for(int y=0;y<m;y++){
if(matrix[x][y][z]==1 && vis[x][y][z]==false){
ans+=BFS(x,y,z);
}
}
}
}
cout<<ans<<endl;
return 0;
}
以上!