ACM题目:连阴雨

ACM题目:连阴雨

要求

时限:1000ms 内存限制:10000K 总时限:3000ms

描述

因为连续的降雨,我们学校操场上出现了许多水坑,现在需要统计一共有多少个水坑。
题目输入为一个N譓 (1 <= N <= 100; 1 <= M <= 100)的图,(‘W’) 代表积水,(‘.’)代表干燥。
一处积水我们认为和它周围的八个方向相邻,相邻的积水构成一个水坑。
需要输出一个数字,表示一共有多少个互不相邻的水坑。

输入

第一行:两个正整数n和m。
第二行到第n+1行:输入操场信息,每一点的状态只可能是’W’ 或者’.’。

输出

输出一个正整数,表示不相邻的水坑的数目。

输入样例

10 12
W……..WW.
.WWW…..WWW
….WW…WW.
………WW.
………W..
..W……W..
.W.W…..WW.
W.W.W…..W.
.W.W……W.
..W…….W.

输出样例

3


思路

本题是深度优先搜索应用的一道题,属于最大联通块问题。
首先建立对应的n行m列的二维数组来存储对应的水坑,再建立与之相同大小的二维数组,用来保存数组的访问信息。
接下来遍历二维数组,当当前位置的元素未被访问并且其值为W时,将当前位置标记为已经访问过了。接着使用深度优先遍历搜索以当前点为中心的八个位置,当这八个位置里有满足未被访问的元素并且值为W的,使用深度优先遍历该节点的八个位置。这样递归下去,就会将一个水坑的所有元素都便利到,这样的一次深度遍历会找到一个水坑,进行几次深度遍历就会得到几个水坑。所以,水坑的次数和深度搜索的次数保持一致。
这样,便可以通过编程来解决这道问题。

java代码

public class Question17 {

    // 全局变量,保存输入的数据
    static int  m,n;
    static char a[][];
    static int vis[][];
    // 水坑计数
    static int number = 0;

    public static void main(String[] args) {
        // 获取用户的输入
        Scanner scanner = new Scanner(System.in);
        n = scanner.nextInt();
        m = scanner.nextInt();
        // 输入的信息数组
        a = new char[n][m];
        // 访问信息数组,vis[i][j] = 0表示未被访问
        vis = new int[n][m];

        // 接收输入的数组,并将访问数组初始化
        for(int i= 0;i<n;i++) {
            String str = scanner.next();
            for(int j=0;j<m;j++) {
                a[i][j] = str.charAt(j);
                vis[i][j] = 0;
            }
        }
        // 关闭输入流
        scanner.close();

        // 对水坑的数据进行判断
        for(int i= 0;i<n;i++) {
            for(int j=0;j<m;j++) {
                // 假如当前ij对应的vis数组值为0表示未被访问且a数组的值为W则进行一次深度优先遍历,计数值加一
                if(vis[i][j]==0&&a[i][j]=='W') {
                    dnf(i,j);
                    number++;
                }
            }
        }

        // 输出结果
        System.out.println(number);

    }

    /**
     * 深度优先遍历
     * @param a
     * @param vis
     * @param i
     * @param j
     */
    private static void dnf(int i, int j) {
        // TODO Auto-generated method stub
        vis[i][j]=1;
        // 对周围八个点进行判断
        for(int x=-1;x<=1;x++) {
            for(int y=-1;y<=1;y++) {
                // 首先该点不超过数组的最小最大边界,并且该数组未被访问过,且该位置的a数组为w
                if(0<=(i+x)&&(i+x)<n&&0<=(j+y)&&(j+y)<m&&vis[i+x][j+y]==0&&a[i+x][j+y]=='W') {
                    dnf(i+x,j+y);
                }
            }
        }
    }

}

猜你喜欢

转载自blog.csdn.net/icarus_wang/article/details/79602291
今日推荐