BFS
一、BFS
BFS,即为宽度优先搜索,思路是先搜索距离初始状态近的状态。按照初始状态->只需一次就可以到达的状态->只需两次就可以。。。。。。
宽度优先搜索采用了队列的思想
框架:
摘自:https://www.cnblogs.com/zhangchengbing/p/3210362.html
二、例题
例一、迷宫最短路径
题目 给定一个大小为N*M的迷宫,迷宫由通道和墙壁组成,,每一步可以向左右上下四个方向走一步,请计算从出发点到终点最少需要多少步,若不能到达终点则输出‘NO’
n,m<=100
input
10 12
W........WW.
.WWW.....WWW
....WW...WW.
.........WW.
.........W..
..W......W..
SW.W.....WW.
W.W.W.....W.
.W.WG.....W.
..W.......W
output
12
题解:因为如果第一步能到达,那么肯定会舍弃第二步,所以可以用bfs算法来解决
代码:
#include<iostream> #include<cstdio> #include<algorithm> #include<queue> #include<utility> #define maxn 110 #define INF 1e6 using namespace std; typedef pair<int,int> P; queue<P>que; char maze[maxn][maxn];//迷宫 int x,y;//迷宫的行数和列数 int d[maxn][maxn];//储存从起点到该点的距离 int dx[]={1,0,-1,0}; int dy[]={0,1,0,-1};//上下左右移动 int beginx,beginy;//迷宫开始的横纵坐标 int endx,endy;//迷宫结束的横纵坐标 void init()//初始化和输入 { while(!que.empty()) que.pop(); scanf("%d%d",&x,&y); for(int i=0;i<x;i++) for(int j=0;j<y;j++) d[i][j]=INF;//初始距离为无穷 for(int i=0;i<x;i++) scanf("%s",maze[i]); for(int i=0;i<x;i++) for(int j=0;j<y;j++) { if(maze[i][j]=='S') { beginx=i; beginy=j; } if(maze[i][j]=='G') { endx=i; endy=j; } } } int bfs(int ix,int iy)//bfs { d[ix][iy]=0; que.push(P(ix,iy)); while(!que.empty()) { P q=que.front();//队列的第一个用front que.pop(); int tx=q.first; int ty=q.second; for(int i=0;i<4;i++) { int xx=tx+dx[i]; int yy=ty+dy[i]; if(xx>=0&&xx<x&&yy>=0&&yy<y)//处在合法的位置 { if(maze[xx][yy]!='W'&&d[xx][yy]==INF) { d[xx][yy]=d[tx][ty]+1; if(maze[xx][yy]=='G') return d[xx][yy]; que.push(P(xx,yy)); } } } } return d[endx][endy]; } int main() { init(); printf("%d\n",bfs(beginx,beginy)); return 0; }
例二、数字迷宫
- 描述这有一个迷宫,有N行和M列:
- 0表示道路,1表示墙。
- 现在输入一个道路的坐标作为起点,再如输入一个道路的坐标作为终点,问最少走几步才能从起点到达终点?
- (注:一步是指从一坐标点走到其上下左右相邻坐标点,如:从(3,1)到(4,1)。)
- 输入
- 第一行输入行数和列数,随后输入N行M列数字
- 输入一个整数n(0<n<=100),表示有n组测试数据;
- 随后n行,每行有四个整数a,b,c,d(0<=a,b,c,d<=8)分别表示起点的行、列,终点的行、列。
- 输出
- 输出最少走几步。
- 样例输入
- 9 9
1 1 1 1 1 1 1 1 1
1 0 0 1 0 0 1 0 1
1 0 0 1 1 0 0 0 1
1 0 1 0 1 1 0 1 1
1 0 0 0 0 1 0 0 1
1 1 0 1 0 1 0 0 1
1 1 0 1 0 1 0 0 1
1 1 0 1 0 0 0 0 1
1 1 1 1 1 1 1 1 1 - 2
3 1 5 7 - 3 1 6 7
样例输出
12
11 - 代码:
- #include<iostream>
#include<algorithm>
#include<utility>
#include<string>
#include<queue>
#define maxn 105
#define INF 1000000
using namespace std;
typedef pair<int,int> P;
int bx,by;//初始点的坐标
int co,ex,ey;//终点的坐标
int N,M;//行数和列数
int a[maxn][maxn];//记录是否被标记
int s[maxn][maxn];//记录地图
queue<P> que;//bfs的队列
int dx[]= {0,0,1,-1},dy[]= {1,-1,0,0}; //上下左右移动
int bfs()
{
while(!que.empty())
{
P p=que.front();
que.pop();
int x=p.first,y=p.second;
if(x==ex&&y==ey)
break;
for(int i=0; i<4; i++)
{
int xx=x+dx[i],yy=y+dy[i];
if(xx>=0&&xx<N&&yy>=0&&yy<M&&a[xx][yy]==INF&&s[xx][yy]!=1)
{
que.push(P(xx,yy));
a[xx][yy]=a[x][y]+1;
}
}
}
return a[ex][ey];
}
int main()
{
while(cin>>N>>M&&M)
{
for(int i=0; i<N; i++)
for(int j=0; j<M; j++)
cin>>s[i][j];
cin>>co;
while(co--)
{
cin>>bx>>by>>ex>>ey;
while(!que.empty())
que.pop();//清空队列
for(int i=0; i<N; i++)
for(int j=0; j<M; j++)
a[i][j]=INF;
a[bx][by]=0;
que.push(P(bx,by));
int ans=bfs();
cout<<ans<<endl;
}
}
return 0;
}
例题三、奇怪的电梯
题目描述
有一天桐桐做了一个梦,梦见了一种很奇怪的电梯。大楼的每一层楼都可以停电梯,而且第i层楼(1≤i≤N)上有一个数字K;(0≤Ki≤N)。电梯只有四 个按钮:开,关,上,下。上下的层数等于当前楼层上的那个数字。当然,如果不能满足要求,相应的按钮就会失灵。例如:3 3 1 2 5代表了Ki (K1=3,K2=3,…),从一楼开始。在一楼,按“上,”可以到4楼,按“下”是不起作用的,因为没有-2楼。那么,从A楼到B楼至少要按几次按钮 呢?
输入
第1行为三个正整数,表示N,A,B(1≤N≤200,1≤A,B≤N);
第2行为N个正整数,表示Ki。
输出
1行,即最少按键次数,若无法到达,则输出-1。
样例输入
5 1 5
3 3 1 2 5
样例输出
3
题解:因为是每一步只有两种选择,每个楼层只会经历一次,因此可以用bfs
代码:
#include<iostream>
#include<algorithm>
#include<utility>
#include<string>
#include<queue>
#include<cstring>
#define maxn 105
#define INF 1000000
using namespace std;
int a[]= {1,-1};
queue<int>que;
int bf,ef;//起始的楼层,最后的楼层
int N;//楼层数
int k[100],fl[100];
int bfs()
{
while(!que.empty())
{
int p=que.front();//初始的层数
que.pop();
if(p==ef)
break;
for(int i=0; i<2; i++)
{
int f=a[i]*k[p];//移动的步数
if(p+f>=1&&p+f<=N&&fl[p+f]==0)
{
que.push(p+f);
fl[p+f]=fl[p]+1;
}
}
}
return fl[ef];
}
int main()
{
while(cin>>N&&N)
{
cin>>bf>>ef;
memset(fl,0,sizeof(fl));
for(int i=1; i<=N; i++)
cin>>k[i];
while(!que.empty())
que.pop();//清空队列
fl[bf]=0;
que.push(bf);
int ans=bfs();
cout<<ans<<endl;
}
return 0;
}
例题四、Catch That Cow
题目: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?
Input
Line 1: Two space-separated integers: N and K
Output
Line 1: The least amount of time, in minutes, it takes for Farmer John to catch the fugitive cow.
Sample Input
5 17
Sample Output
4
Hint
The fastest way for Farmer John to reach the fugitive cow is to move along the following path: 5-10-9-18-17, which takes 4 minutes.
题解:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<string>
#include<queue>
#include<utility>
#include<cstring>
#define maxn 100000
using namespace std;
queue<int>que;
int N,M;
int a[maxn];
int main()
{
while(cin>>N>>M)
{
memset(a,0,sizeof(a));
while(!que.empty())
que.pop();
que.push(N);
a[N]=0;
while(que.size())
{
int k=que.front();
que.pop();
if(k==M)
break;
for(int i=0;i<3;i++)
{
int kk;
if(i==0)
{
kk=k+1;
if(kk>=0&&kk<=maxn&&a[kk]==0)
{
que.push(kk);
a[kk]=a[k]+1;
}
}
if(i==1)
{
kk=k-1;
if(kk>=0&&kk<=maxn&&a[kk]==0)
{
que.push(kk);
a[kk]=a[k]+1;
}
}
if(i==2)
{
kk=k*2;
if(kk>=0&&kk<=maxn&&a[kk]==0)
{
que.push(kk);
a[kk]=a[k]+1;
}
}
}
}
cout<<a[M]<<endl;
}
return 0;
}
浙公网安备 33010602011771号