广度优先:每次都尝试访问同一层的节点。 如果同一层都访问完了,再访问下一层。
这样做的结果是,BFS 算法找到的路径是从起点开始的 最短 合法路径。
在 BFS 结束时,每个节点都是通过从起点到该点的最短路径访问的。
算法过程可以看做是图上火苗传播的过程:
最开始只有起点着火了,在每一时刻,有火的节点都向它相邻的所有节点传播火苗。
模板
q.push(head);
while(!q.empty()){
temp=q.front();
q.pop();
if(temp为目标状态)
输出或记录
if(temp不合法){
continue;
if(temp合法)
q.push(temp+符合题意的数据)
}
例题
Catch That Cow
https://vjudge.csgrandeur.cn/problem/POJ-3278#author=0
题面
Farmer John has been informed of the location of a fugitive cow and wants to catch her immediately. He starts at a point N (0 ≤ N ≤ 100,000) on a number line and the cow is at a point K (0 ≤ K ≤ 100,000) on the same number line. Farmer John has two modes of transportation: walking and teleporting.
- Walking: FJ can move from any point X to the points X - 1 or X + 1 in a single minute
- Teleporting: FJ can move from any point X to the point 2 × X in a single minute.
If the cow, unaware of its pursuit, does not move at all, how long does it take for Farmer John to retrieve it?
输入
Line 1: Two space-separated integers: N and K
输出
Line 1: The least amount of time, in minutes, it takes for Farmer John to catch the fugitive cow.
题意
输入n和k表示农夫和牛的位置,n和k在区间【0,100000】间
农夫有三种方式进行移动,每种方式需要的时间相同,都是一分钟
1.向前移动一米(+1)
2.向后移动一米(-1)
3.移动到2*n(移动到二倍农夫当前米数)
牛不动
求农夫走到牛所在位置的最短时间(分钟)并输出。
ac代码
#include<iostream>
#include<queue>
using namespace std;
const int maxn=1e5+5;
int n,k;
bool vis[maxn];
int ans;
struct p{
int x,s;
}v,u,nn;
inline bool pp(int x){
return x>=0&&x<=100000&&!vis[x];
};
queue<p> q;
void bfs(){
while(!q.empty()){
u=q.front();
q.pop();
if(u.x==k){
ans=u.s;
return;
}
//int xx,ss;
for(int i=1;i<=3;++i){
if(i==1){
nn.x=u.x-1;
}
else if(i==2){
nn.x=u.x+1;
}
else nn.x=u.x*2;
if(pp(nn.x)){
nn.s=u.s+1;
vis[nn.x]=1;
q.push(nn);
}
}
}
}
int main(){
scanf("%d %d",&n,&k);
v.x=n,v.s=0;
vis[n]=1;
q.push(v);
bfs();
printf("%d\n",ans);
}
Lake Counting
题意:有一块N×M的土地,雨后积起了水,有水标记为‘W’,干燥为‘.’。八连通的积水被认为是连接在一起的。请求出院子里共有多少水洼?
输入:第一行为N,M(1≤N,M≤110)。
下面为N * M的土地示意图。
输出:一行,共有的水洼数。
ac代码
#nclude<iostream>
#include<queue>
#define ios ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
using pii = pair<int, int>;
const int inf = 0x3f3f3f3f;
const int maxn = 1e5 + 5;
const int dir[8][2] = { {-1,0},{0,-1},{1,0},{0,1} ,{-1,-1},{-1,1},{1,-1},{1,1}};
int n,m;
char a[1000][1000];
int sum;
queue<pii>q;
void bfs(int x,int y){
a[x][y]='.';
q.push({x,y});
while(!q.empty()){
int xt=q.front().first;
int yt=q.front().second;
q.pop();
for(int i=0;i<8;i++){
int w=xt+dir[i][0];
int e=yt+dir[i][1];
if(w>0&&w<=n&&e>0&&e<=m&&a[w][e]=='W'){
a[w][e]='.';
q.push({w,e});
}
}
}
}
int main() {
ios;
cin>>n>>m;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
cin>>a[i][j];
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(a[i][j]=='W'){
bfs(i,j);
sum++;
}
}
}
cout<<sum<<endl;
return 0;
}
迷宫问题
题意
定义一个二维数组:
int maze[5][5] = {
0, 1, 0, 0, 0,
0, 1, 0, 1, 0,
0, 0, 0, 0, 0,
0, 1, 1, 1, 0,
0, 0, 0, 1, 0,
};
它表示一个迷宫,其中的1表示墙壁,0表示可以走的路,只能横着走或竖着走,不能斜着走,要求编程序找出从左上角到右下角的最短路线。
输入
一个5 × 5的二维数组,表示一个迷宫。数据保证有唯一解。
输出
左上角到右下角的最短路径,格式如样例所示。
反向输出
ac代码
#include<iostream>
#include<queue>
using namespace std;
int map[10][10];
int dx[5]={0,0,1,-1};
int dy[5]={1,-1,0,0};
int vis[10][10];
struct node{
int x,y;
}pr[10][10];
bool pa(int x,int y){
return x<5&&x>=0&&y>=0&&y<5&&!vis[x][y]&&!map[x][y];
}
void bfs(){
queue<node> q;
node p;
p.x=0;
p.y=0;
q.push(p);
vis[0][0]=1;
while(!q.empty()){
node pp=q.front();
if(pp.x==4&&pp.y==4){
return ;
}
q.pop();
for(int i=0;i<4;++i){
p.x=pp.x+dx[i];
p.y=pp.y+dy[i];
if(pa(p.x,p.y)){
vis[p.x][p.y]=1;
q.push(p);
pr[p.x][p.y]=pp;
}
}
}
}
void print(int x,int y){
if(x==0&&y==0){
printf("(%d, %d)\n",x,y);
return;
}
print(pr[x][y].x,pr[x][y].y);
printf("(%d, %d)\n",x,y);
return ;
}
int main(){
for(int i=0;i<5;++i){
for(int j=0;j<5;++j){
scanf("%d",&map[i][j]);
}
}
bfs();
print(4,4);
}