0
点赞
收藏
分享

微信扫一扫

BFS——宽搜详解 图论1.2

上次我们学了dfs,深度优先搜索。

深搜有个缺点,就是“不撞南墙不回头”的遍历太暴力了,所以可能会时间超限,但是代码好写。

我们今天还是来学搜索——宽度优先搜索,bfs。

宽度优先搜索就像涟漪,一圈一圈的向外找。相当于树的层次遍历。搜完一层再搜一层·。

假设你现在站在一个路口的n点,你从地图里知道这附近一共k个商店,你想知道你从这里到m号商店,最少经过多少个商店。这样你有可能会从你的位置向外找路,因为这样效率高。你看,你在心中运行了BFS。

bfs是一种比较暴力的搜索(比dfs还暴力?),不搜到目标就不停,就是说你得一直找下去,不断地向外找,直到你找到了那个店。如果你真的这么干的,会累死的。

我送你一段模板代码,剩下的给我自己写去!!


void bfs()
{
    front=rear=0;
    a[sx][sy]=标记,不能走的;
    qx[rear]=sx,qy[rear++]=sy;
    step[sx][sy]=0;
    while(front!=rear)
    {
        int tx=qx[front];
        int ty=qy[front++];
        if(目标状态)
        {
            执行目标操作;
            return;
        }
        for(int i=0;i<4;i++)
        {
            int fx=tx+dx[i],fy=ty+dy[i];
            if(越界)
            {
                continue;
            }
            if(没走过这个点,也就是这个点能走)
            {
                当前点入队;
                qx[rear]=fx;
                qy[rear++]=fy;
                a[fx][fy]=标记上;
            }
        }
    }
}

这是基本的bfs代码,因为这个模板是搜图的,要加方向数组。看着就暴力,没走过就走,记住这个路,我走过了不再走了,最后找到目标,好了,发送数值,你的任务完成了。

其实很适用于飞机搜目标。看看地上的路,搜完一条,没有,记住这条路别再搜了,然后再找。如果目标不移动,这样就算花一天,你也十有八九能找到他。

感觉好暴力啊……

不说了,做题吧……

小可走迷宫

时间限制:2秒        内存限制:256M

题目描述

小可置身于一个迷宫,每走一步只能向上下左右四个方向移动,请你帮小可找出从起点到终点的最短路程。

输入描述

输入包含多组测试数据。输入的第一行是一个整数T,表示有T组测试数据。
每组输入的第一行是两个整数N和M(1<=N,M<=100)。
接下来N行,每行输入M个字符,每个字符表示迷宫中的一个小方格。
字符的含义如下:
‘S’:起点
‘E’:终点
‘-’:空地,可以通过
‘#’:障碍,无法通过
输入数据保证有且仅有一个起点和终点。

输出描述

对于每组输入,输出从起点到终点的最短路程,如果不存在从起点到终点的路,则输出-1。

样例

输入

1
5 5
S-###
-----
##---
E#---
---##

输出

9

这里我要提醒一下,宽搜是不用那么麻烦求最小步数的。因为宽搜的思想原因,他找出来的必定是最短路。但是这个不是GPS用的算法,GPS用的叫迪杰斯特拉,算最短路比这个还快,我后面会讲。

这个很明显的宽搜,但是宽搜有个毛病,他需要在传参数的时候判断终点。深搜就不这样,深搜是在搜的时候看看有没有到终点。

这个题终点条件是‘E’。所以我们先把主函数写好:



int main(){
    for(int k=0;k<t;k++){
        ff=0;
        memset(step,0,sizeof step);
        cin>>x>>y;
        for(int i=1;i<=x;i++)
        {
            for(int j=1;j<=y;j++)
            {
                cin>>a[i][j];
                if(a[i][j]=='S') sx=i,sy=j;
                if(a[i][j]=='E') ex=i,ey=j;
            }
        }
        //输出,特判-1
    }
    
}

我还是只给一部分,剩下的自己写!!

bfs函数基本照抄模板,只要改几个判断就好了。这里我不给代码了,自己试着改一下,有问题找我调。

接下来我们再来一个:

奇怪的电梯

题目描述

假设一栋大楼有一种很奇怪的电梯。大楼的每一层楼都可以停电梯,而且第i层楼(1<=i<=N)上有一个数字Ki(0<=Ki<=N)。电梯只有四个按钮:开,关,上,下。上下的层数等于当前楼层上的那个数字。当然,如果不能满足要求,相应的按钮就会失灵。例如:3 3 1 2 5代表了Ki(K1=3,K2=3,……),从一楼开始。在一楼,按“上”可以到4楼,按“下”是不起作用的,因为没有-2楼。那么,从A楼到B楼至少要按几次按钮呢?

输入描述

第1行为3个正整数,表示N,A和B,1<=N<=200,1<=A,B<=N;

第2行为N个正整数,表示Ki。

输出描述

一行,共一个数,即最少按键次数。若无法到达,则输出-1。

样例

输入

5 1 5
3 3 1 2 5

输出

3

解析:

不很明显,电梯跟搜索哪门子关系?实际这也是宽搜。

一看至少,马上明白。按楼层搜就好了。

代码不给了,自己写吧,有事找我

家庭作业:

迷宫

时间限制:1秒        内存限制:128M

题目描述

一天小可在森林里探险的时候不小心走入了一个迷宫,迷宫可以看成是由n * n的格点组成,每个格点只有2种状态,.和#,前者表示可以通行后者表示不能通行。同时当小可处在某个格点时,他只能移动到东南西北(或者说上下左右)四个方向之一的相邻格点上,小可想要从点A走到点B,问在不走出迷宫的情况下能不能办到。如果起点或者终点有一个不能通行(为#),则看成无法办到。

输入描述

第1行是测试数据的组数k,后面跟着k组输入。每组测试数据的第1行是一个正整数n (1 ≤ n ≤ 100),表示迷宫的规模是n * n的。接下来是一个n * n的矩阵,矩阵中的元素为.或者#。再接下来一行是4个整数ha, la, hb, lb,描述A处在第ha行, 第la列,B处在第hb行, 第lb列。注意到ha, la, hb, lb全部是从0开始计数的。

输出描述

k行,每行输出对应一个输入。能办到则输出“YES”,否则输出“NO”。

样例

输入

2
3
.##
..#
#..
0 0 2 2
5
.....
###.#
..#..
###..
...#.
0 0 4 0

输出

YES
NO

注意啊是个多组输入,要while输入

好了,下课吧。下次我们讲位运算和用位运算优化的搜索。

举报

相关推荐

0 条评论