• 【DFS】求水洼的数目


    题目:

      有一个大小为 N*M 的园子,雨后积起了水。八连通的积水被认为是连接在一起的。请求出园子里总共有多少水洼?(八连通指的是下图中相对 W 的*的部分)

    ***
    *W*
    ***

      限制条件:N, M ≤ 100

      样例输入:

    N=10, M=12

      园子如下图('W'表示积水, '.'表示没有积水)

    W........WW.
    .WWW.....WWW
    ....WW...WW.
    .........WW.
    .........W..
    ..W......W..
    .W.W.....WW.
    W.W.W.....W.
    .W.W......W.
    ..W.......W.

      输出:

    3

    思路:

      这道题目很经典,值得以后多去研究研究。问题是要我们求解出连着的一片的水洼的数量,对于这类经典的问题,使用其它迭代等的方法是难以求解的,因为我们不知道连着的积水的区域有多少,对于这类问题的求解,我们是采用常用的无死角搜索的深度优先搜索dfs算法来解决,因为dfs能够帮助我们搜索出所有的可能,尝试去走每一条路线,直到所有的路线都被走完了,那么dfs就终止了。

      其中涉及到搜索以自己为中心的八个方向的搜索,所以存在着八个平行状态的搜索,这里使用到了一个技巧就是使用两层的for循环来进行处理。

      这里还有一个技巧就是当发现这个位置有积水的时候就把这个位置变为干燥,这样在往下搜索的过程中就能避免往上搜索而造成递归无法出去的问题。这样当一个dfs搜索完之后那么它周围的积水都被清除掉了,那么继续寻找下一个有积水的地方然后进行dfs,当所有的积水区域都被干燥之后那么水洼的数量就计算出来了。

    代码:  

     1 import java.util.Scanner;
     2 
     3 public class 水洼数 {
     4 
     5     private static int n;
     6     private static int m;
     7 
     8     public static void main(String[] args) {
     9         Scanner sc = new Scanner(System.in);
    10         n = sc.nextInt();
    11         m = sc.nextInt();
    12         char[][] a = new char[n][];
    13         for (int i = 0; i < n; i++) {
    14             a[i] = sc.next().toCharArray();
    15         }
    16         int cnt = 0;
    17         for (int i = 0; i < n; i++) {
    18             for (int j = 0; j < m; j++) {
    19                 if (a[i][j] == 'W') {
    20                     dfs(a, i, j);// 清除一个水洼
    21                     cnt++;
    22                 }
    23             }
    24         }
    25         System.out.println(cnt);
    26     }
    27 
    28     private static void dfs(char[][] a, int i, int j) {
    29         a[i][j] = '.';
    30 
    31         for (int k = -1; k < 2; k++) {// -1,0,1
    32             for (int l = -1; l < 2; l++) {// -1,0,1
    33                 if (k == 0 && l == 0)
    34                     continue;
    35 
    36                 if (i + k >= 0 && i + k <= n - 1 && j + l >= 0 && j + l <= m - 1) {
    37                     if (a[i + k][j + l] == 'W')
    38                         dfs(a, i + k, j + l);
    39                 }
    40             }
    41         }
    42     }
    43 
    44 }

    结果:

      

  • 相关阅读:
    Android SQLite 建立多表间的主外键关系 Binary
    Android——扩大ImageButton的点击区域 Binary
    Android——刷新媒体库 Binary
    Oracle数据导入导出imp/exp命令 10g以上expdp/impdp命令 转自:南水江的鸽子窝
    在同一应用中混合使用ASP.NET窗体和ASP.NET MVC 转自:geez的个人空间
    ASP.NET WebApplication 发布部署
    Oracle 导出索引Sequence!!
    获取ORACLE 表字段,表名,以及主键之类等等的信息
    FlexGrid 控件的使用 摘自:大道至简
    整合 DZNT到自己网站
  • 原文地址:https://www.cnblogs.com/xiaoyh/p/10347236.html
Copyright © 2020-2023  润新知