• POJ 2386 Lake Counting 题解《挑战程序设计竞赛》


    地址 http://poj.org/problem?id=2386

    《挑战程序设计竞赛》习题

    题目描述
    Description

    Due to recent rains, water has pooled in various places in Farmer John’s field, which is represented by a rectangle of N x M (1 <= N <= 100; 1 <= M <= 100) squares. Each square contains either water (‘W’) or dry land (‘.’). Farmer John would like to figure out how many ponds have formed in his field. A pond is a connected set of squares with water in them, where a square is considered adjacent to all eight of its neighbors.

    Given a diagram of Farmer John’s field, determine how many ponds he has.


    Input

    Line 1: Two space-separated integers: N and M

    Lines 2..N+1: M characters per line representing one row of Farmer John’s field. Each character is either ‘W’ or ‘.’. The characters do not have spaces between them.
    Output

    Line 1: The number of ponds in Farmer John’s field.

    样例

    Sample Input
    
    10 12
    W........WW.
    .WWW.....WWW
    ....WW...WW.
    .........WW.
    .........W..
    ..W......W..
    .W.W.....WW.
    W.W.W.....W.
    .W.W......W.
    ..W.......W.
    Sample Output
    
    3

    算法1
    将相同的水坑算在一起 并查集

    C++ 代码

    #include <iostream>
    #include <set>
    
    using namespace std;
    
    #define MAX_NUM 110
    
    int N, M;
    char field[MAX_NUM+10][MAX_NUM + 10];
    int fa[MAX_NUM*MAX_NUM];
    
    //char field[10][12] = {
    //  {'W','.','.','.','.','.','.','.','.','W','W','.'},
    //  {'.','W','W','W','.','.','.','.','.','W','W','W'},
    //  {'.','.','.','.','W','W','.','.','.','W','W','.'},
    //  {'.','.','.','.','.','.','.','.','.','W','W','.'},
    //  {'.','.','.','.','.','.','.','.','.','W','.','.'},
    //  {'.','.','W','.','.','.','.','.','.','W','.','.'},
    //  {'.','W','.','W','.','.','.','.','.','W','W','.'},
    //  {'W','.','W','.','W','.','.','.','.','.','W','.'},
    //  {'.','W','.','W','.','.','.','.','.','.','W','.'},
    //  {'.','.','W','.','.','.','.','.','.','.','W','.'}
    //};
    
    
    //===============================================
    // union find
    void init(int n)
    {
        for(int i=1;i<=n;i++)
            fa[i]=i;
    }
    int get(int x)
    {
        return fa[x]==x?x:fa[x]=get(fa[x]);//路径压缩,防止链式结构
    }
    void merge(int x,int y)
    {
        fa[get(x)]=get(y);
    }
    //===========================================================
    
    
    
    void Check(int x,int y)
    {
        //
        int xcopy = x - 1;
        if (xcopy >= 0 && x < N) {
            for (int add = -1; add <= 1; add++) {
                int ycopy = y + add;
                if (ycopy >= 0 && ycopy < M && field[xcopy][ycopy] == 'W') {
                    int idx = x * M + y;
                    int anotherIdx = xcopy * M + ycopy;
                    merge(idx, anotherIdx);
                }
            }
        }
    
        //
        xcopy = x;
        if (xcopy >= 0 && x < N) {
            for (int add = -1; add <= 1; add++) {
                if (add == 0) continue;
                int ycopy = y + add;
                if (ycopy >= 0 && ycopy < M && field[xcopy][ycopy] == 'W') {
                    int idx = x * M + y;
                    int anotherIdx = xcopy * M + ycopy;
                    merge(idx, anotherIdx);
                }
            }
        }
    
    
        //
        xcopy = x + 1;
        if (xcopy >= 0 && x < N) {
            for (int add = -1; add <= 1; add++) {
                int ycopy = y + add;
                if (ycopy >= 0 && ycopy < M && field[xcopy][ycopy] == 'W') {
                    int idx = x * M + y;
                    int anotherIdx = xcopy * M + ycopy;
                    merge(idx, anotherIdx);
                }
            }
        }
    }
    
    
    int main()
    {
        cin >> N >> M;
        //N = 10; M = 12;
    
        init(MAX_NUM*MAX_NUM);
    
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < M; j++) {
                cin >> field[i][j];
                if (field[i][j] == 'W') {
                    //检查上下左右八个方向是否有坑
                    Check(i,j);
                }
            }
        }
        set<int> s;
    
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < M; j++) {
                if (field[i][j] == 'W') {
                    int idx = i * M + j;
                    //cout << "fa["<<idx << "] = "<< fa[idx] << endl;
                    s.insert(get(idx));
                }
            }
        }
    
        cout << s.size() << endl;
    
        return 0;
    }
    
    
    作者:defddr
    链接:https://www.acwing.com/solution/acwing/content/3674/
    来源:AcWing
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

    算法2
    DFS 遍历 将坐标连续的坑换成. 计数+1

    C++ 代码

    #include <iostream>
    
    using namespace std;
    
    int N, M;
    int unitCount = 0;
    
    #define MAX_NUM 110
    
    char field[MAX_NUM + 10][MAX_NUM + 10];
    
    //char field[10][12] = {
    //    {'W','.','.','.','.','.','.','.','.','W','W','.'},
    //    {'.','W','W','W','.','.','.','.','.','W','W','W'},
    //    {'.','.','.','.','W','W','.','W','W','W','W','.'},
    //    {'.','.','.','.','.','.','.','.','.','W','W','.'},
    //    {'.','.','.','.','.','.','.','.','.','W','.','.'},
    //    {'.','.','W','.','.','.','.','.','.','W','.','.'},
    //    {'.','W','.','W','.','.','.','.','.','W','W','.'},
    //    {'W','.','W','.','W','.','.','.','.','.','W','.'},
    //    {'.','W','.','W','.','.','.','.','.','.','W','.'},
    //    {'.','.','W','.','.','.','.','.','.','.','W','.'}
    //};
    
    
    void Dfs(int x, int y)
    {
        //终止条件
        if (x < 0 || x >= N || y < 0 || y >= M || field[x][y] == '.')
            return;
    
        field[x][y] = '.';
    
        Dfs(x + 1, y - 1); Dfs(x + 1,y); Dfs(x + 1, y + 1);
        Dfs(x , y-1);                Dfs(x , y + 1);
        Dfs(x -1, y-1); Dfs(x - 1, y); Dfs(x - 1, y +1);
    
    }
    
    int main()
    {
        cin >> N >> M;
        //N = 10; M = 12;
    
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < M; j++) {
                cin >> field[i][j];
            }
        }
    
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < M; j++) {
                if (field[i][j] == 'W'){
                    unitCount++;
                    Dfs(i,j);
                }
            }
        }
    
        cout << unitCount << endl;
    
        return 0;
    }
    作 者: itdef
    欢迎转帖 请保持文本完整并注明出处
    技术博客 http://www.cnblogs.com/itdef/
    B站算法视频题解
    https://space.bilibili.com/18508846
    qq 151435887
    gitee https://gitee.com/def/
    欢迎c c++ 算法爱好者 windows驱动爱好者 服务器程序员沟通交流
    如果觉得不错,欢迎点赞,你的鼓励就是我的动力
    阿里打赏 微信打赏
  • 相关阅读:
    负载均衡原理与实践详解 第十六篇 负载均衡网络设计 把负载均衡当作二层交换机还是三层路由器
    谈谈我对技术发展的一点感悟
    解析索引中数据列顺序的选择问题
    构建高性能.NET应用之配置高可用IIS服务器第四篇 IIS常见问题之:工作进程回收机制(上)
    关注分离的艺术(The Art of Separation of Concerns)
    如何修改.net framework
    [WPF Documents 之旅]System.Windows.Documents下的Class Diagram
    [转] 依赖注入&控制反转 oC 容器和Dependency Injection 模式(中文版)
    [WPF疑难]如何禁用窗口上的关闭按钮
    关于书写技术探讨性邮件的一点小小的建议
  • 原文地址:https://www.cnblogs.com/itdef/p/11332128.html
Copyright © 2020-2023  润新知