广度优先搜索——BFS遍历

 广度优先搜索(Breadth First Search , BFS)是一个分层搜索的过程,没有回退过程,是非递归的

为避免重复访问,需要一个状态数组visited[n]来存储各顶点的访问状态。为实现逐层访问,bfs算法在实现时需要一个队列,以记忆正在访问的这一层和上一层的顶点,以便于向下一层访问。

例题(1):营救(rescue)

输入描述:"."  :道路  "r" :Angle的朋友 "#" :墙壁  "x" :警卫

分析:本题要求从r位置出发到达Angel所在的位置且所需时间最少,适合bfs求解。但在本题中,步数最少的解不一定是最优解。

为求出最优解,采用如下的思路进行bfs搜索。

(1)将Angel的朋友到达某个方格的状态用一个结构体point表示,该结构体包含了Angel的朋友到达该方格时所走过的步数及所花费的时间;在bfs搜索中,队列中的结点是point型数据.

(2)定义一个二维数组mintime,mintime[i][j]表示Angel的朋友走到(i,j)位置所需的最少时间;在bfs搜索过程中,从当前位置走到相邻的位置(x,y)时,只有当该种走法比走到(x,y)所需的时间更少时,才会把当前走到(x,y)位置的状态入队列,否则是不会入队列的。

(3)不能一判断出到达目标位置就退出bfs过程,否则求出的最小时间仅仅是从r到达a最小步数的若干方案中的最小时间,不一定是最优解,一定要等到队列为空,才能得出结论。

另外在题目中未使用visited[n]数组,因为只有当下一个位置比上一个所需的时间少才能入队列,所以到达(x,y)的最少时间肯定是有下界的。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<queue>
#define maxint 0x3f3f3f3f
#define MAXN 200
using namespace std;
struct point
{
    int x,y;
    int step;
    int time;
};
queue<point>Q;
int n,m;
char map[MAXN][MAXN];
int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
int mintime[MAXN][MAXN];
int ax,ay;///Angel所在的位置
int bfs(point s);
int main()
{
    int i,j;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        memset(mintime,maxint,sizeof(mintime));
        memset(map,0,sizeof(map));
        for(i=0;i<n;i++)
            scanf("%s",map[i]);
        int sx,sy;
        point start;
        for(i=0;i<n;i++)
            for(j=0;j<m;j++)
        {
            if(map[i][j]=='a'){ax=i,ay=j;}
            else if(map[i][j]=='r'){sx=i,sy=j;}
        }
        start.x=sx;
        start.y=sy;
        start.step=0;
        start.time=0;
        mintime[sx][sy]=0;
        int mint=bfs(start);
        if(mint<maxint)
            printf("%d\n",mint);
        else
            printf("can not arrived\n");
    }
    return 0;
}
int bfs(point s)
{
    int i,j;
    Q.push(s);
    point hd;///队列头的位置
    while(!Q.empty())
    {
        hd=Q.front();
        Q.pop();
        for(i=0;i<4;i++)
        {
            int x=hd.x+dir[i][0];
            int y=hd.y+dir[i][1];
            if(x>=0&&y>=0&&x<=n-1&&y<=m-1&&map[x][y]!='#')
            {
                point t;
                t.x=x;
                t.y=y;
                t.step=hd.step+1;
                t.time=hd.time+1;
                if(map[x][y]=='x') t.time++;///杀死警卫的时间
              ///如果比最少时间少,则将t入队列
                if(t.time<mintime[x][y])
                {
                    mintime[x][y]=t.time;
                    Q.push(t);
                }
            }
        }
    }
    return mintime[ax][ay];
}
广度优先搜索的伪代码

(1)若用邻接表存储图

dfs(顶点i)
{
    visited[i]=1;
    将顶点i入队列;
    while(队列不为空)
    {
        取出队列头的顶点,设为k;
        p=顶点k的边链表表头指针;
        while(p不为空)
        {
            ///设指针p指向的边结点所表示的边的另一个顶点为j;
            if(顶点j未访问过)
            {
                将顶点j标记为访问;
                将顶点j入队列;
            }
            p=p->next;
        }
    }
}

(2)用邻接矩阵存储图

dfs(顶点i)
{
    visited[i]=1;
    将顶点i入队列;
    while(队列不为空)
    {
        取出队列头的顶点,设为k;
        for(j=0;j<n;j++)
        {
              ///j是k的邻接点,且未被访问过
            if(map[k][j]==1&&!visited[j])
            {
                将顶点j标记为访问;
                将顶点j入队列;
            }
        }
     }
}



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值