宽度优先搜索算法

一、宽度优先搜索算法

        对于以上“无向图”,从顶点 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;
}


结束!

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值