zoukankan      html  css  js  c++  java
  • 广度(宽度)优先搜索学习笔记

                                                      广度(宽度)优先搜索学习笔记

    2015-08-24  22:29:53:

    宽度优先搜索算法(又称广度优先搜索)是最简便的图的搜索算法之一,这一算法也是很多重要的图的算法的原型。Dijkstra单源最短路径算法和Prim最小生成树算法都采用了和宽度优先搜索类似的思想。其别名又叫BFS,属于一种盲目搜寻法,目的是系统地展开并检查图中的所有节点,以找寻结果。换句话说,它并不考虑结果的可能位置,彻底地搜索整张图,直到找到结果为止。

    BFS,其英文全称是Breadth First Search。 BFS并不使用经验法则算法。从算法的观点,所有因为展开节点而得到的子节点都会被加进一个先进先出的队列中。一般的实验里,其邻居节点尚未被检验过的节点会被放置在一个被称为 open 的容器中(例如队列或是链表),而被检验过的节点则被放置在被称为 closed 的容器中。(open-closed表)

    以上内容摘自百度百科= = 


    个人见解:

    DFS一条路搜到底,不到南墙不回头。BFS则为搜索周围扩展的节点然后在扩展,一般用队列实现。


    基本框架:

     1 Int bfs()
     2 
     3 {
     4 
     5 初始化,初始状态存入队列;
     6 
     7 队列首指针head=0; 尾指针tail=1 8 
     9 do
    10 
    11  {
    12
    13     指针head后移一位,指向待扩展结点;
    14 
    15     for (int i=1;i<=max;++i)                  //max为产生子结点的规则数
    16 
    17      {
    18 
    19       if (子结点符合条件)
    20 
    21          {
    22 
    23            tail指针增1,把新结点存入列尾;
    24 
    25            if (新结点与原已产生结点重复) 删去该结点(取消入队,tail减1);
    26 
    27    else
    28 
    29        if (新结点是目标结点) 输出并退出;
    30 
    31               }
    32 
    33          }
    34 
    35 }while(head<tail);                       //直到队列为空
    36 
    37 }

    PS:不要问窝为什么有空行,我踏马怎么知道


    TI:                                                                  细胞个数

    题目描述 Description

    一矩形阵列由数字0到9组成,数字1到9代表细胞,细胞的定义为沿细胞数字上下左右还是细胞数字则为同一细胞,求给定矩形阵列的细胞个数。如阵列:

    0234500067
    1034560500
    2045600671
    0000000089
    有4个细胞。

    输入描述 Input Description

    【输入格式】

    整数m,n

    (m行,n列)矩阵

    输出描述 Output Description

    【输出格式】

    细胞的个数。

    样例输入 Sample Input

    4  10

    0234500067
    1034560500
    2045600671
    0000000089

    样例输出 Sample Output

    4

    数据范围及提示 Data Size & Hint

    1<=m,n<=1000


    思路:基本的BFS,搜索每个细胞,然后扩展该细胞上下左右,若还是细胞就入队,再搜扩展的细胞……直到搜完整个图。


    程序:

     1 #include<iostream>
     2 #include<cstdio>
     3 using namespace std;
     4 int dx[4]={-1,0,1,0},dy[4]={0,1,0,-1};  //上下左右四个方向  
     5 int num=0,n,m; 
     6 char bz[2000][2000]; 
     7 void search(int p,int q)
     8 {
     9     int x,y,w,t,i;
    10     int h[1000][2];
    11     num++;//细胞数字数+1;
    12     bz[p][q]='0';
    13     t=0;
    14     w=1;
    15     h[1][1]=p; 
    16     h[1][2]=q;  //初始化头尾指针及队列的第一组
    17         do
    18       {
    19           t++;//头指针+1
    20           for (i=0;i<=3;i++)//枚举四个方向
    21             {
    22                 x=h[t][1]+dx[i];//下一个扩展节点的坐标
    23                 y=h[t][2]+dy[i];
    24                 if ((x>=0)&&(x<10)&&(y>=0)&&(y<10)&&(bz[x][y]!='0')) //边界判断及是否为细胞数字
    25               {
    26                   w++;//尾指针+1
    27                   bz[x][y]='0';//已搜索过
    28                   h[w][1]=x;
    29                   h[w][2]=y;//入队
    30               } 
    31             }
    32       } 
    33     while (t<w); 
    34 } 
    35 int main()
    36 {
    37     freopen("puzzle.in","r",stdin);
    38     freopen("puzzle.out","w",stdout);
    39     int i,j;
    40 for(int i=0;i<=9;i++)
    41 for(int j=0;j<=9;j++)
    42    bz[i][j]='1';
    43     for (i=0;i<=9;i++)
    44           for (j=0;j<=9;j++)
    45             cin>>bz[i][j]; //读入
    46     for (i=0;i<=9;i++)
    47       for (j=0;j<=9;j++)
    48         if (bz[i][j]!='0')
    49           search(i,j);//搜索每个细胞数字
    50             printf("%d",num);
    51     return 0; 
    52     fclose(stdin);
    53     fclose(stdout);
    54 }

    T2:武士风度的牛

    题目描述 Description

          农民John有很多牛,他想交易其中一头被Don称为The Knight的牛。这头牛有一个独一无二的超能力,在农场里像Knight一样地跳(就是我们熟悉的象棋中马的走法)。虽然这头神奇的牛不能跳到树上和石头上,但是它可以在牧场上随意跳,我们把牧场用一个x,y的坐标图来表示。

    这头神奇的牛像其它牛一样喜欢吃草,给你一张地图,上面标注了The Knight的开始位置,树、灌木、石头以及其它障碍的位置,除此之外还有一捆草。现在你的任务是,确定The Knight要想吃到草,至少需要跳多少次。The Knight的位置用'K'来标记,障碍的位置用'*'来标记,草的位置用'H'来标记。

    这里有一个地图的例子:
           11 | . . . . . . . . . .
           10 | . . . . * . . . . . 
           9 | . . . . . . . . . . 
           8 | . . . * . * . . . . 
           7 | . . . . . . . * . . 
           6 | . . * . . * . . . H 
           5 | * . . . . . . . . . 
           4 | . . . * . . . * . . 
           3 | . K . . . . . . . . 
           2 | . . . * . . . . . * 
           1 | . . * . . . . * . . 
           0 ----------------------
                      1 
            0 1 2 3 4 5 6 7 8 9 0 

    The Knight 可以按照下图中的A,B,C,D...这条路径用5次跳到草的地方(有可能其它路线的长度也是5):
           11 | . . . . . . . . . .
           10 | . . . . * . . . . .
           9 | . . . . . . . . . .
           8 | . . . * . * . . . .
           7 | . . . . . . . * . .
           6 | . . * . . * . . . F<
           5 | * . B . . . . . . .
           4 | . . . * C . . * E .
           3 | .>A . . . . D . . .
           2 | . . . * . . . . . *
           1 | . . * . . . . * . .
           0 ----------------------
                      1
            0 1 2 3 4 5 6 7 8 9 0 

    输入描述 Input Description

    第一行: 两个数,表示农场的列数(<=150)和行数(<=150)

    第二行..结尾: 如题目描述的图。

    输出描述 Output Description

         一个数,表示跳跃的最小次数。

    样例输入 Sample Input

    10 11
    ..........
    ....*.....
    ..........
    ...*.*....
    .......*..
    ..*..*...H
    *.........
    ...*...*..
    .K........
    ...*.....*
    ..*....*..

    样例输出 Sample Output

    5

    数据范围及提示 Data Size & Hint

    Hint:这类问题可以用一个简单的先进先出表(队列)来解决。


    思路:与细胞数字相同,将上下左右四个方向换为象棋中马八个方向即可,从起始位置开始搜索。


    出现的错误:RE-->八个方向的数组开小了。何时该加w和t;


    程序:

     1 #include <iostream>
     2 using namespace std;
     3 struct data
     4 {
     5     int x,y,step;
     6 }
     7 dl[30001];
     8 int jump2[9]={1,2,2,1,-1,-2,-2,-1},
     9     jump1[9]={-2,-1,1,2,2,1,-1,-2};
    10 int n,m,i,w,j,t,x1,x2,y1,y2,x3,y3;
    11 int a[200][200];
    12 char q;
    13 void bfs()
    14 {
    15     if (x1==x2&&y1==y2)
    16       {
    17           cout<<0;
    18           return;
    19       } 
    20     t=0;
    21     w=1;
    22     dl[t].x=x1;
    23     dl[t].y=y1;
    24     dl[t].step=0;
    25     while (t<w)
    26       {
    27           for (i=0;i<=8;i++)
    28             {
    29                 x3=dl[t].x+jump1[i];
    30                 y3=dl[t].y+jump2[i];
    31                 if (a[x3][y3]!=1&&x3<=n&&x3>=1&&y3>=1&&y3<=m)
    32                   {
    33                        a[x3][y3]=1;
    34                        dl[w].x=x3;
    35                        dl[w].y=y3;
    36                        dl[w].step=dl[t].step+1;
    37                        if (dl[w].x==x2&&dl[w].y==y2)
    38                          {
    39                                cout<<dl[w].step;
    40                                return;
    41                          }
    42                        w++;
    43                   }
    44             }
    45           t++;
    46       }
    47 }
    48 int main()
    49 {
    50     cin>>m>>n;
    51     for (i=1;i<=n;i++)
    52       for (j=1;j<=m;j++)
    53         {
    54             cin>>q;
    55         if (q=='*') a[i][j]=1;
    56         if (q=='K') {x1=i;y1=j;}
    57         if (q=='H') {x2=i;y2=j;}
    58         }
    59     bfs();    
    60     return 0;
    61 }

     

     

    —Anime Otaku Save The World.
  • 相关阅读:
    取近似值
    eclipse 自己主动为getter和setter加入中文凝视
    Linux对外连接port数限制
    C++链表冒泡,归并,插入排序(纯指针)
    Android之实现ViewPager+Fragment左右滑动
    获得鼠标离开消息。
    CMFCPropertyGridProperty的使用
    阅读书单
    Docker 容器管理
    docker rmi 详解
  • 原文地址:https://www.cnblogs.com/DMoon/p/4756139.html
Copyright © 2011-2022 走看看