zoukankan      html  css  js  c++  java
  • 广度优先搜索介绍

    这道题的原址:http://blog.csdn.net/johsnows/article/details/52997282

    BFS是一种盲目搜寻法,目的是系统地展开并检查图中的所有节点,以找寻结果。换句话说,它并不考虑结果的可能位置,彻底地搜索整张图,直到找到结果为止。BFS并不使用经验法则算法

                                                                                                                                                                                                                       --------百度百科

    搜索其实算一种暴力枚举的算法,不过这种暴力枚举是一种有条理性的暴力枚举, 更容易控制以及实现。它在求最短路以及遍历图或树的时候会用到。

    说它是一种暴力枚举的算法是因为,如同百科提到的,它在搜索的时候仍然会遍历整张图中的所有节点,而它的条理性则体现在它用一个队列记录每一步搜索的状态,每一步新加入的状态都会加入队列,用于下一次搜索,并且状态会被继承。这种在图上实现的搜索不仅容易实现,也容易记录每一步的状态,用于求出答案(如最短路)。


    建图方式:

    邻接矩阵:二维数组: a[x][y]。x表示横坐标,y表示纵坐标,a[x][y]即代表这个点的状态。

    邻接表: 指针数组:

    [cpp] view plain copy
     在CODE上查看代码片派生到我的代码片
    1. struct ljb  
    2. {  
    3.     int y;  
    4.     int z;  
    5. }*a[x];  

    当题目所给的图过大,横纵坐标的最大值超过二维数组能开的空间时,可以使用邻接表。a[x]代表每一行的头结点。列和状态用链表的结点记录,挂在对应行的头结点之后。这样可以存下一个足够大的图,当然操作起来会更麻烦。 



    用于下一步搜索的next数组:

    [cpp] view plain copy
     在CODE上查看代码片派生到我的代码片
    1. int next[4][2]={{0,1}, {1,0}, {0,-1}, {-1, 0}};  

           每一行的值分别代表向上右下左走一步,这样可以直接用一层for来实现向下一步搜索。

    如dx=x+next[i][0], dy=y+next[i][1];
          
     

    另外虽然是枚举,但是已经走过点应当避免重复枚举,所有用一个book[x][y]数组记录该点是否已经走过。


           下面通过一个简单的用bfs求解的问题来讲解

           题目:给出一个长为n宽m的地图,起点x,y和终点sx,sy,以及M个障碍物(不能经过的点),问从起点到终点最少需要经过多少步数。

           关于bfs的用法就在代码中具体述说了:

    [cpp] view plain copy
     在CODE上查看代码片派生到我的代码片
    1. #include <iostream>  
    2. #include <cstdio>  
    3. using namespace std;  
    4. const int maxn=1e3+5;  
    5. bool book[maxn][maxn]; //记录是否已经走过这个点  
    6. int t[maxn][maxn]; //邻接矩阵  
    7. int n,m;  
    8. int next[4][2]={{0,1}, {1,0}, {0,-1}, {-1, 0}};  
    9. struct p  
    10. {  
    11.     int x; //横坐标  
    12.     int y; //纵坐标  
    13.     int s; // 当前步数  
    14. }a[maxn];//用队列记录将要搜索的点  
    15. int bfs(int x, int y, int sx, int sy)  
    16. {  
    17.     int head, tail, i, j;  
    18.     head=tail=0; //队头队尾初始化为0  
    19.     a[head].x=x;  
    20.     a[head].y=y;  
    21.     a[head].s=0;//将起点加入队列,队列头的点表示当前要走的点  
    22.     tail++;  
    23.     while(head<tail)  
    24.     {  
    25.   
    26.        if(a[head].x==sx && a[head].y==sy) //如果当前点就是终点,则返回这个点的步数  
    27.        {  
    28.            return a[head].s;  
    29.        }  
    30.        int dx, dy; //表示当前的点能够走的点的坐标  
    31.        for(i=0; i<4; i++) //枚举四个可以走的方向  
    32.        {  
    33.                dx=a[head].x+next[i][0];   
    34.                dy=a[head].y+next[i][1];  
    35.                if(dx>=0 && dx<=n && dy>=0 && dy<=m && t[dx][dy]!=-1) // 如果这个可以走的点不在图中或者是障碍物就不进行搜索,即不加入队列  
    36.                if(book[dx][dy]==0 ) //book数组等于0表示这个点之前没有搜索过,可以走  
    37.                {  
    38.                    a[tail].x=dx;  
    39.                    a[tail].y=dy;  
    40.                    a[tail].s=a[head].s+1; //将这个点加入队尾,将在之后搜索,它的步数应当等于当前点所走的步数再加上一。  
    41.                    tail++;  
    42.                    book[dx][dy]=1;//已经加入队列,标记已经搜索过,避免接下来重复搜索  
    43.                }  
    44.        }   
    45.           head++;// <strong>让已经搜索过的点出队</strong>,容易忘记  
    46.     }  
    47.     return -1; // 假如队列为空,即所有的点都已经搜索过了,但是并没有函数return结束,说明没能找到目标点,则返回-1表示不能到达  
    48. }  
    49. int main()  
    50. {  
    51.    int x, y, sx, sy;  
    52.     int M;  
    53.     scanf("%d%d%d%d%d%d", &n, &m, &x, &y, &sx, &sy);  
    54.   
    55.   
    56.     scanf("%d", &M);  
    57.     int i;  
    58.     memset(t, 0, sizeof(t)); //初始化图  
    59.     for(i=0; i<M; i++)  
    60.     {  
    61.         int xx,yy;  
    62.         scanf("%d%d", &xx, &yy);  
    63.         t[xx][yy]=-1; //将障碍物标记为-1  
    64.     }  
    65.     int ans=bfs(x,y,sx,sy);  
    66.     printf("%d\n", ans);  
    67.     return 0;  
    68. }  
  • 相关阅读:
    恢复 root 本地无权限 Access denied for user 'root'@'localhost' (using password: NO)
    linux 下 PHP Notice: session_start(): ps_files_cleanup_dir 报错 问题剖析
    linux 下mysql 开启远程连接
    linux 下mysql 字段插入的值超过 预设大小报错
    CSS、HTML5、JS
    WPF、Sivelright、UWP
    Quartz.net作业调度
    nginx+iis、NLB、Web Farm、Web Garden、ARR
    workflow
    SqlSugar ORM
  • 原文地址:https://www.cnblogs.com/CCCrunner/p/6444582.html
Copyright © 2011-2022 走看看