赞
踩
BFS,其英文全称是 Breadth First Search,意为广度优先搜索,是所有的搜索手段之一。它是从某个状态开始,将所有节点加入一个先进先出的队列,然后一层一层进行状态转移,并且展开节点。
作为搜索算法的一种,BFS 相较于 DFS 而言,BFS 是一层一层展开的,那么对于有多个终态时,最先找到的一定是最短的。
按照定义设计:
int check(参数) { if(满足条件) return 1; return 0; } bool pd(参数){ 相应操作 } void bfs() { 1. 把根节点放入队列尾端 2. 每次从队列中取出一个节点 3. Check 判断是不是答案,如果是结束算法 return; 4. 把当前取出的节点扩展,如果扩展后的节点经Pd()后符合要求,就放入队列,不符合就不放。 5. 转到步骤2,循环执行 } 如果所有节点被扩展完了,没有找到答案就无解。
BFS搜索的原理:逐层扩散,从起点出发,按层次从近到远,逐层先后搜索
编码:用队列实现
应用:BFS一般用于求最短路径问题,BFS的特点是逐层搜索,先搜到的层离起点更近
找从@到*最短路径
步骤 | 出队列 | 进队列 | 当前队列内的点 |
---|---|---|---|
(1) | 1 | 1 | |
(2) | 1 | 2、3 | 2、3 |
(3) | 2 | 4、5、6 | 3、4、5、6 |
(4) | 3 | 7、8 | 4、5、6、7、8 |
BFS的特点:逐层扩散
题目链接
难度: 简单
标签: 模拟, BFS, 2020, 省模拟赛
题目描述:
小明有一块空地,他将这块空地划分为 n 行 m 列的小块,每行和每列的长度都为 1。
小明选了其中的一些小块空地,种上了草,其他小块仍然保持是空地。
这些草长得很快,每个月,草都会向外长出一些,如果一个小块种了草,则它将向自己的上、下、左、右四小块空地扩展,
这四小块空地都将变为有草的小块。请告诉小明,k 个月后空地上哪些地方有草。
输入描述:
输入的第一行包含两个整数 n,m。
接下来 n 行,每行包含 m 个字母,表示初始的空地状态,字母之间没有空格。如果为小数点,表示为空地,如果字母为 g,表示种了草。
接下来包含一个整数 k。 其中,2≤n,m≤1000,1≤k≤1000
输出描述:
输出 n 行,每行包含 m 个字母,表示 k 个月后空地的状态。如果为小数点,表示为空地,如果字母为 g,表示长了草。
输入输出样例:
示例:
输入:
4 5
.g...
.....
..g..
.....
2
输出:
gggg.
gggg.
ggggg
.ggg.
运行限制:
最大运行时间:1s
最大运行内存: 256M
解题思路:
这个题目简直就是为了广度优先搜索设置模板题,由于这个题目是输出广度优先搜索 K
次扩展后的终态,那我们就不用设置判断函数。
这里用一个 N×M 的矩阵来表示草地。
g
的草地的位置加入队列,然后向下执行2
判断边界,符合就放入队列,不符合就跳过。Check
,判断符不符合题意,有没有剪枝…C++ 语言描述:
#include <bits/stdc++.h> using namespace std; const int M = 1005; struct PII { int first; int second; }; // C++ 有个数据类型叫 pair 上面的就可以定义为 pair<int,int> 用起来比较方便。 PII tempPair;//临时结点 char Map[M][M]; //---------图的路径搜索常用方向移动表示------- int dx[4]= {0,1,-1,0}; int dy[4]= {1,0,0,-1}; // 两两组合形成上下左右四个方向 // 1------------------> x // | // | // | // | // | // | // | // ↓ // y // dx[0]=0 dy[0]=1 那么代表向下的方向 // dx[1]=1 dy[1]=0 那么代表向右的方向 // dx[2]=-1 dy[2]=0 那么代表向左的方向 // dx[3]=0 dy[3]=-1 那么代表向上的方向 int n;// n 行 int m;// m 列 int k;// k 次 queue<PII > q; //广度优先搜索所用的队列 int len;//记录节点数量方便后续k的计算 bool pd(int x, int y) { if(x<1) return 0; // /x 轴坐标 左侧越界 else if(x>n) return 0; //x 轴坐标 右侧越界 else if(y<1) return 0; //y 轴坐标 上侧越界 else if(y>m) return 0; //y 轴坐标 下侧越界 else if(Map[x][y]=='g') return 0; //已经长草了 else return 1; // 在范围内,且没长草 } void BFS() { //BFS while(!q.empty()&&k>0) { tempPair = q.front(); q.pop(); //这两步是取出队首的节点 int x = tempPair.first;//横坐标 int y = tempPair.second;//纵坐标 for(int i=0; i<4; i++) { int nowx = x+dx[i]; //扩展后的横坐标 int nowy = y+dy[i]; //扩展后的纵坐标 if(pd(nowx,nowy)) { q.push({nowx,nowy}); Map[nowx][nowy]='g'; } //符合要求执行扩展,不符合要求,忽略即可。 } len--; //每取出一个节点len -1 if(len==0) { //当len =0 时,代表当前层扩展完了,那么就代表第一个月扩展完了 k--; // 所以k-- len = q.size(); // 当前层扩展完了,那就该扩展下一层了,所以len又被赋值为下一层的节点数目的值 } } } int main() { cin>>n>>m; for(int i=1; i<=n; i++) { for(int j=1; j<=m; j++) { cin>>Map[i][j]; if(Map[i][j]=='g') { tempPair.first=i; tempPair.second=j; // cout<<i<<""<<j<<endl; q.push(tempPair);//将初始有树的结点加入队列 } } } len = q.size();//记录第一层的节点数量方便后续k的计算 cin>>k; BFS(); for(int i=1; i<=n; i++) { for(int j=1; j<=m; j++) { cout<<Map[i][j]; } cout<<endl; } return 0; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。