一、宽度优先搜索算法
对于以上“无向图”,从顶点 V0 开始进行宽度优先搜索,得到的一个序列为 V0,V1,V2,V3,V4,V6,V5。
二、BFS算法
宽度优先搜索是一种“盲目”搜索,所有结点的拓展都遵循“先进先出”的原则,所以采用“队列”来存储这些状态。
void BFS{
while (front <= rear){
// 当队列非空时做,front 和 rear 分别表示队列的头指针和尾指针
if (找到目标状态)
做相应处理(如退出循环输出解、输出当前解、比较解的优劣);
else{
拓展头结点 ;
if( 拓展出的新结点没出现过 ){
rear++;
将新结点插到队尾 ;
}
}
front++;// 取下一个结点
}
}
三、例题代码
1.图的宽度优先搜索
#include<bits/stdc++.h>
using namespace std;
int a[105][105],f,r,b[105];
bool flag[105];
int main(){
freopen("rela.in","r",stdin);
freopen("search.out","w",stdout);
int n;
cin>>n;
memset(flag,true,sizeof(flag));
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
cin>>a[i][j];
}
}
f=r=1;
cout<<1;
b[r]=1; //入队
flag[1]=false;
int x;
while(f<=r){
x=b[f];
for(int i=1;i<=n;i++){
if(a[x][i]==1 && flag[i]){
r++;
b[r]=i; //入队
flag[i]=false;
cout<<"-"<<b[r];
}
}
f++;
}
return 0;
}
2.关系网络
【问题描述】
有 n 个人,编号为 1~n。其中有一些人相互认识,现在 x 想要认识 y,可以通过他所认识的人来认识更多的人(如果 a 认识 b、b 认识 c,那么 a 可以通过 b 来认识 c),求出 x 最少需要通过多少人才能认识 y。
【输入格式】 第 1 行 3 个正整数 n、x、y,其中:n≤100,1≤x、y≤n。 接下来是一个 n×n 的邻接矩阵,a[i,j]=1 表示 i 认识 j,a[i,j]=0 表示 i 不认识 j。 保证 i=j 时,a[i,j]=0,并且 a[i,j] =a[j,i],一行中的两个数之间有一个空格。
【输出格式】 输出一行一个数,表示 x 认识 y 最少需要通过的人数。
代码:
#include<bits/stdc++.h>
using namespace std;
int a[1011][101],step[101],flag[101];
int n,x,y;
int bfs(){
queue<int> q;
q.push(x); //从x开始找
step[x]=0;
flag[x]=1;
while(!q.empty()){
int t=q.front();
q.pop();
if(t==y){
return step[t];
}
else{
for(int i=1;i<=n;i++){ //t的朋友
if(a[t][i]==1 && flag[i]==0){
q.push(i);
cout<<"---"<<t<<"-"<<i<<endl;
step[i]=step[t]+1;
flag[i]=1;
}
}
}
}
}
int main(){
freopen("rela.in","r",stdin);
freopen("rela.out","w",stdout);
cin>>n>>x>>y;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
cin>>a[i][j];
}
}
cout<<bfs()-1; //中间的步数
return 0;
}
3.
【问题描述】 在一个 w×h 的矩形广场上,每一块 1×1 的地面都铺设了红色或黑色的瓷砖。小林同学站在某一块黑色的瓷砖上,他可以从此处出发,移动到上、下、左、右四个相邻的且是黑色的瓷砖上。现在,他想知道,通过重复上述移动所能经过的黑色瓷砖数。
【输入格式】 第 1 行为 h、w,2≤w、h≤50,之间由一个空格隔开; 以下为一个 w 行 h 列的二维字符矩阵,每个字符为“.”“#”“@”,分别表示该位置为黑色的瓷砖、红色的瓷砖、小林的初始位置。
【输出格式】 输出一行一个整数,表示小林从初始位置出发经过的黑色瓷砖数。
【输入样例】
11 9
. # . . . . . . . . .
. # . # # # # # # # .
. # . # . . . . . # .
. # . # . # # # . # .
. # . # . . @ # . # .
. # . # # # # # . # .
. # . . . . . . . # .
. # # # # # # # # # .
. . . . . . . . . . .
【输出样例】 59
代码:
//BFS宽度
#include<iostream>
#include<queue>
using namespace std;
int w,h;//瓷砖宽和高
char room[100][100];//存放瓷砖数据
int x0,y0;//起点位置
int num=0;//记录一共有多少可走的瓷砖
int d[2][4]={{-1,0,1,0},{0,1,0,-1}}; //上右下左
struct node{
int x;
int y;
};
bool check(int x,int y){
if(x>=0&&x<w&&y>=0&&y<h) return 1;
else return 0;
}
//逻辑如下:
//1.将起点加入到队列中;
//2.如果队列不为空,开始搜索入队列,当前位置的上下左右 依次入队列
//入队列时需要判断是否越界,是否是"."
//3.弹出队首
//4.直到队列为空,结束搜索
void bfs(int x,int y){
queue <node> brick;
node start,next;
start.x=x,start.y=y;
brick.push(start);//将起点加入到队列中;
num=1;//起点可走,所以赋值位1
while(!brick.empty()){//搜索入队列,当前位置的上下左右 依次入队列
start =brick.front();
cout<<start.x<<"---"<<start.y<<endl;
for(int i=0;i<4;i++){
next.x=start.x+d[0][i];
next.y=start.y+d[1][i];
if(check(next.x,next.y)&&room[next.x][next.y]=='.'){//判断是否越界,是否是"."
brick.push(next);
num++;
room[next.x][next.y]='#';
}
}
brick.pop();
}
}
int main(){
//主函数逻辑分三步:读入瓷砖数据;搜索瓷砖;输出数量
freopen("tile.in","r",stdin);
freopen("tile.out","w",stdout);
//1.读入矩阵数据 for循环,并记录起点位置
cin>>h>>w;//列行
for(int i=0;i<w;i++){
for(int j=0;j<h;j++) {
cin>>room[i][j];
if(room[i][j]=='@'){
x0=i;
y0=j;
}
}
}
//2.用宽度优先算法搜索
bfs(x0,y0);
//3.输出个数
cout<<num;
return 0;
}
结束!