2.1.5 宽度优先搜索(BFS) (《挑战程序设计竞赛》)

宽度优先搜索

核心是按照距开始状态由近及远的顺序进行搜索,即先找完第一步的情况,再找完第二步的情况,再找完第三步的情况……
所以,可以很容易地找到最短路径,最少操作之类的问题的答案。


例题:
这里写图片描述
样例答案是22

代码:

#include<iostream>
#include<stdio.h>
#include<queue>
using namespace std;
const int INF=100000000;
typedef pair<int, int>P;
char maze[100][100];
int N,M;
int sx,sy,gx,gy;
int d[100][100];
int dx[4]={1,0,-1,0},dy[4]={0,1,0,-1};
int bfs()
{
    queue<P> que;
    int nx,ny;
    for(int i=0;i<N;i++)
        for(int j=0;j<M;j++) d[i][j]=INF;
    que.push(P(sx,sy));
    d[sx][sy]=0;
    while(que.size())
    {
        //用大P来定义小p,即小p存放的是一对横纵坐标,que存的也是横纵坐标
        P p=que.front(); 
        que.pop(); //取出队列最前端的元素
        if(p.first==gx && p.second==gy) break; //能够到达就break;
        for(int i=0;i<4;i++)
        {
            nx=p.first+dx[i],ny=p.second+dy[i];
            if(0<=nx&&nx<N &&0<=ny&&ny<M&&maze[nx][ny]!='#'&&d[nx][ny]==INF)
            {
                que.push(P(nx,ny)); //注意是大P
                d[nx][ny]=d[p.first][p.second]+1;
            }
        }
    }
    return d[gx][gy];
}
int main()
{
   // freopen("a.txt","r",stdin);
    int i,j,res;
    scanf("%d%d%d%d%d%d",&N,&M,&sx,&sy,&gx,&gy);
    for(i=0;i<N;i++) scanf("%s",maze[i]);
    res=bfs();
    cout<<res;
}

其中:
maze数组用来记录迷宫
d数组用来记录起点到当前坐标的距离,d[2][4]即起点到位置(2,4)走了多少步
dx和dy 是用来控制四方位:
dx[0],dy[0] 即(1,0),意为向右走一步
dx[1],dy[1] 即(0,1),意为向下走一步
dx[2],dy[2] 即(-1,0),意为向左走一步
dx[3],dy[3] 即(0,-1),意为向上走一步

typedef pair<int, int> P; //用来记录横纵坐标

代码的思路是:
先把起点加入队列,然后每次while,记录队列的最前面的元素(记为小p)后,取出,代表当前状态开始搜索。然后从当前元素(小p)的四个方向搜索 不越界 且 不是墙 且 没有走过 的位置,这些位置就可以走动。把可以走动的位置加入队列,然后记录可以走的位置到起点的距离,它们都是比当前位置(p)距离多1。
队列每一个轮回,每条路径都走1步,有的路径走到头,没有可以走动的位置,就不加入队列;有的路径只有一步可走,便只加入一次队列;有的路径遇到分岔路口,便多次加入队列,即一条路径发展出多条路径,且他们的步数一致。


总结:
整个程序下来,统计出1步能到达的位置,且是否到达终点,没有的话统计2步能到达的位置,如果还没有一条路径到达终点,则统计3步能到达的位置……
如此下来就能求出抵达终点的最短路径。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值