深度优先搜索(续)

Posted 中学生编程与信息学竞赛自学

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了深度优先搜索(续)相关的知识,希望对你有一定的参考价值。

注意:本文用到了初中的数学知识以及C++的编程代码。

编程学习最好使用计算机, 请登陆 www.3dian14.org 学习更多的编程知识。


今天继续看一个深度优先搜索的经典例子。


在一次降雨中,雨水汇集在某块农田中,该农田由N×M(1 <= N <= 100; 1 <= M <= 100)小正方形方格组成的矩形。每个方格或者其中有积水(用“W”表示)或者还是干地(用“.”表示)。现在想弄清楚农田里到底形成了多少个池塘。池塘是一组相互连接的方格,每个方格中都有水,注意这里每个方格与它相邻的八个方格都看成是连接的。对于给定的田地的图形,请找出其中有多少个池塘。


输入
第1行:两个以空格分隔的整数:N和M,分别表示该田地由N×M个方格组成。
第2..N + 1行:每行M个字符,分别对应田地的一行方格。每个字符都是“W”或“.”。字符之间没有空格。
输出:农田中的池塘数量。


下面是一种输入样例:


深度优先搜索(续)


依据池塘的定义,对于有水的W方格S,相邻的左上,上方、右上、左方、右方、左下、下方、右下的任何一个有W的方格,都是与S连通的,都是属于同一个池塘的。可以看出在其中包含有三个池塘,见下图所示。

深度优先搜索(续)

解题思路


池塘其实是连通的积水格子。


我们采用深度优先DFS的算法。从第一行第一列的方格开始,依次对W方格利用深度优先法DFS进行检测。


对于某个W方格S1,S1必定属于一个池塘,我们只要依次检查位于S1左上,上方、右上、左方、右方、左下、下方、右下的邻居方格,看它们是否也是W。我们首先把S1涂成“.”,表示它已经检测过了,接着对于S1的每一个W邻居N,也采用同样的方法进行检测,也就是首先把N也从“W”涂成“.”,表示已经检查过了,也按同样依次检查N的邻居。


当一个W方格的所有W邻居都已是“.”了,则返回上层继续检测。这样可以把与S1连通的所有积水格子都设置成“.”。最后统计一共进行了多少次DFS计算,就是池塘的个数。


算法复杂度

每个格子有八个方向,每个方向对应一种状态转移,每次状态转移时,对每个格子最多检测一次,因此复杂度是O(8*N*M),也就是O(N*M)。


程序实现


下面是C/C++的类代码:

//输入
int N,M;
char field[N_LIMIT][M_LIMIT];//数组,存放对应方格当前状态(W或.)


//当前检测的方格坐标(x,y),x的取值为0..N-1, y的取值为0..M-1,对应第x+1行、y+1列的方格
void dfs(int x, int y)
{
   field[x][y] = '.'; //将当前位置“W”设为“.”,表示已经访问过,下次无须再访问。
  
   //对应八个方向,循环检测
   for (int dx=-1; dx<=1; dx++)
   {
      for (int dy=-1; dy<=1; dy++)
      {
          // 邻居坐标为(n_x,n_y)
          int n_x = x+dx;
          int n_y = y+dy;
         

            //判断邻居方格坐标(n_x,n_y)是否越界         

          if (0<=n_x && n_x<N && 0<=n_y && n_y<M)
          {

                //如果该邻居是W,则表示需要进一步对它进行探测

                 if (field[n_x][n_y]=='W')
                         dfs(n_x,n_y);
          }
      }
   }
   return;
}

void pondnum()
{
    int num = 0; //连通水域的池塘个数
      }

    for (int i=0;i<N;i++){
        for (int j=0;i<M;j++){
        
       //如果找到一个W的积水格子,则采用深度优先算法探索所有与它相连通的格子
           if(field[i][j]=='W'){
             dfs(i,j);
             num++;//统计顶层所有调用dfs的次数,也就是连通水域的池塘个数
          }
       }

   }

   printf("%d ",num);

}




以上是关于深度优先搜索(续)的主要内容,如果未能解决你的问题,请参考以下文章

数据结构与算法图遍历算法 ( 深度优先搜索 DFS | 深度优先搜索和广度优先搜索 | 深度优先搜索基本思想 | 深度优先搜索算法步骤 | 深度优先搜索理论示例 )

深度优先搜索法和广度优先搜索法

基本算法——深度优先搜索(DFS)和广度优先搜索(BFS)

深度优先搜索算法解释下?

简述深度优先搜索遍历的方法。

Python算法-深度优先搜索&广度优先搜索(DFS&BFS)