• 步步为营(十六)搜索(二)BFS 广度优先搜索


    上一篇讲了DFS,那么与之相应的就是BFS。也就是 宽度优先遍历,又称广度优先搜索算法。

    首先,让我们回顾一下什么是“深度”:

    更学术点的说法,能够看做“单位距离下,离起始状态的长度”

    那么广度是什么呢?
    个人认为,能够这么归纳:

    何为广度? 能够看做“距离初始状态距离相等的结点”的集合

    那么BFS的核心思想就是:从初始结点開始,搜索生成第一层结点。检查目标结点是否在这些结点中,若没有,再将全部第一层的结点逐一进行搜索,得到第二层结点,并逐一检查第二层结点中是否包括目标结点。若没有,再继续搜索第二层全部结点……,如此依次扩展,直到发现目标结点为止。

    这样就保证了:假设我如今找到了目标结点(也能够称作当前问题的解)。那么我之前肯定没有发现过目标结点,并且因为是广度优先搜索。所以当前的解一定是距离起始结点近期的,也就是最优解。因为第一个解就是最优解,那么我们就能够尝试打印出道路。

    伪代码例如以下:

    queue 结点队列
    queue.push(起始节点)
    while(结点队列不为空)
    {
        queue.front();
        queue.pop();//取出头结点
    
        if(头结点是目标结点)
        {
            跳出循环。
        }
        for(对下一层结点进行推断) 
        {
            if(结点满足筛选条件)
            {
                queue.push(满足帅选条件的结点)
            }
        }
    }

    那么对于上一篇文章中果园的地图,我们的部分状态是这种:
    S 0 1 1 0
    0 1 0 0 0
    0 0 1 1 0
    0 1 0 0 0
    0 0 0 0 G

    从S点開始,设S点坐标为(1,1)
    (1,1)
    ->(1,2)//第一层
    ->(2,1)//第一层
    ->(3,1)//第二层
    ->(3,2)//第三层
    ->(4,1)//第三层
    ……
    ->(5,5)//找到目标结点,结束

    BFS因为维护了一个队列。所以节省了递归须要消耗的时间,可是空间上却比递归消耗的多的多。假设须要找多个解或者每一个节点的状态比較多。可能会面临空间超限的情况。

    所以:

    1. 求多个解,首先考虑DFS;
    2. 求单个解,首先考虑BFS

    代表题目:HDU 1072 Nightmare

    题目大意:在迷宫中有一个炸弹,过六个单位时间就会爆炸。要你求一个起点到迷宫的终点的最短距离,迷宫中有时间重置器,当你走到这个格子。炸弹的爆炸时间又一次置为0,迷宫中标识为墙壁的格子不能走。到达随意一个格子时,炸弹计数器为0时,则失败。

    解题思路:最短距离。就想到用宽度优先遍历,可是要一个辅助的数组来保存每一个格子的时间信息。因为每一个格子前进一步的花费时间单位是一样的,所以宽度遍历的结果自然是最短距离。因为时间单位有限制。仅仅能走六个单元,仅仅有在这六个时间单位里到达了终点,或者走到了时间设置开关把炸弹计时器置为0才干继续走下去,所以要一个辅助数组来保存每一个格子剩余的最大时间单位,仅仅有走到当前的格子的剩余时间单位比之前的大时。这个状态才干增加队列中。

    以下是代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <queue>
    #include <algorithm>
    
    using namespace std;
    
    struct node
    {
        int x, y;
        int step;
        int t;
    };
    
    const int maxn = 9;
    
    int dir[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
    int maze[maxn][maxn], graph[maxn][maxn];
    int n, m, ex, ey, ans;
    
    bool bfs(int x, int y);
    
    int main()
    {
    
        int test;
        scanf("%d", &test);
        while(test-- != 0)
        {
            scanf("%d %d", &n, &m);
            int sx, sy;
            for(int i = 0; i < n; i++)
            {
                for(int j = 0; j < m; j++)
                {
                    scanf("%d", &maze[i][j]);
                    if(maze[i][j] == 2)
                        sx = i, sy = j;
                    if(maze[i][j] == 3)
                        ex = i, ey = j;
                    graph[i][j] = 0;
                }
            }
            if(bfs(sx, sy))
                printf("%d
    ", ans);
            else
                printf("-1
    ");
        }
    
        return 0;
    }
    
    bool bfs(int x, int y)
    {
        queue<node> que;
        node s;
        s.x = x;
        s.y = y;
        s.step = 0;
        s.t = 6;
        graph[x][y] = 6;
        que.push(s);
        while(!que.empty())
        {
            node st = que.front();
            que.pop();
            if(st.x == ex && st.y == ey)
            {
                ans = st.step;
                return true;
            }
            if(st.t == 1)
                continue;
            for(int i = 0; i < 4; i++)
            {
                int dx = st.x + dir[i][0];
                int dy = st.y + dir[i][1];
    
                if(dx >= 0 && dx < n && dy >= 0 && dy < m && maze[dx][dy] != 0)
                {
                    node tmp;
                    tmp.x = dx; tmp.y = dy;
                    tmp.step = st.step + 1;
                    tmp.t  = st.t - 1;
                    if(maze[dx][dy] == 4)
                        tmp.t = 6;
                    if(tmp.t > graph[dx][dy])
                    {
    
                        graph[dx][dy] = tmp.t;
                        que.push(tmp);
                    }
                }
            }
        }
        return false;
    }
    
  • 相关阅读:
    windows ip路由
    linux ip命令和ifconfig命令
    工作项目技术总结
    网络安全体系
    网络适配器输入的IP地址 已经分配给另一个适配器
    Android笔记之ImageView设置图片以灰色显示
    js小功能
    html2canvas截取图片跨域解决办法
    JS学习笔记(二).eq()与[]的区别
    jQuery中常用的元素查找方法总结
  • 原文地址:https://www.cnblogs.com/gccbuaa/p/7209297.html
Copyright © 2020-2023  润新知