BFS算法入门

      BFS:就是宽度优先搜索,他是搜索算法的一种,他是怎么搜索的呢?先这样说吧:假如在你是一个高度近视的人,在路上走着的时候一不小心,眼睛掉了,那么此时你会怎么办?很简单啊,赶紧蹲下来摸自己的眼睛啊,但是此时的你是看不见的,因为你高度近视,所以你便会蹲下来,用自己的手开始去摸地,去寻找自己的眼睛,下面我们就谈谈找眼睛这个事情,你会怎么在地上用你的双手去摸自己的眼睛呢?很简单啊,先从自己身边找,自己身边没有在尝试着往远的地方找,再想一下,如果你已经找过的地方你还会不会去找啊,肯定不会啊,而且每次你往外扩散的时候,是不是一圈一圈的往外找,其实BFS就是这个意思。它是从某个状态出发,探索所有可能到达的状态,他是按照开始状态\rightarrow只需一次转移就可以到达的所有状态\rightarrow只需二次转移就可以到达的所有状态\rightarrow...............这样的顺序一直搜索下去。还有就是对于同一个状态,BFS只搜索一次不会再去搜索第二次了。

下面来实际模拟一下BFS的过程:

由橙色位置出发,进行BFS:

 下面开始搜此时橙色位置能到达的所有位置:

 灰色位置表示已经走过,橙色表示当前位置。

然后再从此时的橙色位置出发,已经走过的位置就不在走了。

 

 接着搜索:

 

然后:

 

此时已经到达终点了,当前的步数就是最短的步数。

这就是一个BFS的大致过程了,下面再跟一道典型的BFS的题再来详细的介绍一下BFS:

Angel was caught by the MOLIGPY! He was put in prison by Moligpy. The prison is described as a N * M (N, M <= 200) matrix. There are WALLs, ROADs, and GUARDs in the prison. 

Angel's friends want to save Angel. Their task is: approach Angel. We assume that "approach Angel" is to get to the position where Angel stays. When there's a guard in the grid, we must kill him (or her?) to move into the grid. We assume that we moving up, down, right, left takes us 1 unit time, and killing a guard takes 1 unit time, too. And we are strong enough to kill all the guards. 

You have to calculate the minimal time to approach Angel. (We can move only UP, DOWN, LEFT and RIGHT, to the neighbor grid within bound, of course.) 

Input

First line contains two integers stand for N and M. 

Then N lines follows, every line has M characters. "." stands for road, "a" stands for Angel, and "r" stands for each of Angel's friend. 

Process to the end of the file. 

Output

For each test case, your program should output a single integer, standing for the minimal time needed. If such a number does no exist, you should output a line containing "Poor ANGEL has to stay in the prison all his life." 

Sample Input

7 8
#.#####.
#.a#..r.
#..#x...
..#..#.#
#...##..
.#......
........

Sample Output

13

 

这就是一道典型的用BFS搜索来走迷宫的一道题,下面我们开始模拟一下走迷宫的过成:

 

这是一个迷宫,蓝色表示起点,红色表示终点,黑色表示不能通过,白色表示可以通过,适用最小的步数从起点走到终点:

 

 

 

 

 

 

 

 

 

 

这个就是走迷宫的大致上的全过程了,首先我们会从起点出发,然后走下一步可以走的点,然后再走下一步可以走的点,再依次往下走,所以我们在用代码是实现BFS的时候,会用到队列,就是走一步,把此时的状态放进队列里面,然后等到这个节点走完以后,再从队列里拿出一个节点,接着往下走,当这个队列里面没有元素或者走到终点时,那么这个搜索就结束了,还有就是我们每次走过的点我们要标记一下,防止下次再走。我们还要知道每次能走哪几个方向,比如这个题而言,我们能走的就是上下左右,所以我们每一个节点往下走的时候都应该把这四个方向走一遍,如果是一维空间那么每次只需要走两个方向了,至于究竟要走哪几个方向还是要根据题意的,

下面给出AC代码:

#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
const int maxn=205;
char ch[maxn][maxn];
int dis[maxn][maxn];//做为标记如果这个点搜索过了标记为1,没有搜索过标记为0;
int d[4][2]={1,0,-1,0,0,1,0,-1};//能走的四个方向;
int n,m;
int edx,edy,enx,eny;
struct stu
{
    int x;
    int y;
    int step;
}A,B;
void bfs(int x,int y)
{
    queue<stu> que;
    A.x=x;
    A.y=y;
    A.step=0;
    dis[x][y]=1;
    que.push(A);
    int cnt=-1;
    while(!que.empty())
    {

        A=que.front();//把队列的顶端元素取出,
        que.pop();
        if(A.x==enx&&A.y==eny)//如果找到了终点那么搜索就结束了。
        {
            cnt=A.step;
            break;
        }
        for(int i=0;i<4;i++)//一个节点可以走的四个方向,
        {
            B.x=A.x+d[i][0];
            B.y=A.y+d[i][1];
            if(B.x>=0&&B.x<n&&B.y>=0&&B.y<m&&dis[B.x][B.y]==0&&ch[B.x][B.y]!='#')//判断这一步能不能走;
            {
                if(ch[B.x][B.y]=='x') B.step=A.step+2;
                else B.step=A.step+1;
                dis[B.x][B.y]=1;//这个点已经走过,所以要标记下来;
                que.push(B);//把走的这个节点放进队列里面;
            }
        }
    }
   if(cnt == -1) puts("Poor ANGEL has to stay in the prison all his life.");
	else
        printf("%d\n", cnt);

}
int main()
{
    while(~scanf("%d %d",&n,&m ))
    {
        A.step=0;
        B.step=0;
        memset(dis,0,sizeof(dis));
        for(int i=0;i<n;i++)
            scanf("%s",ch[i]);
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<m;j++)
            {
                if(ch[i][j]=='a')
                {
                    edx=i;
                    edy=j;
                }
                if(ch[i][j]=='r')
                {
                    enx=i;
                    eny=j;
                }
            }
        }
        bfs(edx,edy);
    }
    return 0;
}

 

  • 5
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值