hiho一下[156周]:岛屿

给你一张某一海域卫星照片,你需要统计:

  1. 照片中海岛的数目

  2. 照片中面积不同的海岛数目

  3. 照片中形状不同的海岛数目

其中海域的照片如下,”.”表示海洋,”#”表示陆地。在”上下左右”四个方向上连在一起的一片陆地组成一座岛屿。

.####..  
.....#.  
####.#.  
.....#.  
..##.#.  

上图所示的照片中一共有4座岛屿;其中3座面积为4,一座面积为2,所以不同面积的岛屿数目是2;有两座形状都是”####”,所以形状不同的岛屿数目为3。

输入
第一行包含两个整数:N 和 M,(1 ≤ N, M ≤ 50),表示照片的行数和列数。

以下一个 N * M 的矩阵,表示表示海域的照片。

输出
输出3个整数,依次是照片中海岛的数目、面积不同的海岛数目和形状不同的海岛数目。

样例输入

5 7
.####..  
.....#.  
####.#.  
.....#.  
..##.#.  
样例输出
4 2 3

思路很简单,直接dfs即可,不过,需要在搜索的过程中,记录#的数量,来表示面积,记录遍历路径,使用相对位置表示形状。

参考代码(很长,很乱,仅供参考,不建议复制粘贴):

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <set>
#include <map>

struct point {//用一个结构体的表示路径中的点,方便记录岛屿的形状
    int x;
    int y;
    point(int m, int n) {
        x = m;
        y = n;
    }
};
struct mycomp//形状set kind的自动以排序函数
{
    bool operator () (const std::vector<point>& a, const std::vector<point>& b) const
    {
        if (a.size() == b.size()) {
            for (int i = 0; i < a.size(); i++) {
                if (a[i].x == b[i].x) {
                    if (a[i].y == b[i].y) {
                        continue;
                    }
                    return a[i].y > b[i].y;
                }
                return a[i].x > b[i].x;
            }
            return false;
        }
        return a.size() > b.size();
    }
};
void dfs(int i, int j, std::vector<std::vector<bool> > &visited, std::vector<std::vector<char> > &grid, int &area, std::vector<point> &points) {//dfs主要实现函数
    int n = grid.size();
    int m = grid[0].size();
    if (i < 0 || i >= n)
        return;
    if (j < 0 || j >= m)
        return;
    if (visited[i][j] || grid[i][j] == '.')
        return;
    visited[i][j] = true;
    point p(i, j);
    points.push_back(p);
    area++;
    dfs(i - 1, j, visited, grid, area, points);
    dfs(i + 1, j, visited, grid, area, points);
    dfs(i, j - 1, visited, grid, area, points);
    dfs(i, j + 1, visited, grid, area, points);
}
int main() {
    using namespace std;
    int n, m;
    while (cin >> n >> m) {
        vector<vector<char> > grid(n, vector<char>(m));
        vector<vector<bool> > visited(n, vector<bool>(m, false));
        int islandNums = 0;
        set<int> areas;//面积集合,表示不同面积的岛屿个数
        set<vector<point>, mycomp > kinds;//形状集合,表示不同形状的岛屿个数
        int area = 0;
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                cin >> grid[i][j];
            }
        }
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                if (grid[i][j] == '#' && !visited[i][j]) {
                    vector<point> points;
                    dfs(i, j, visited, grid, area, points);
                    islandNums++;
                    areas.insert(area);
                    area = 0;
                    for (int k = points.size() - 1; k >= 0; k--) {
                        points[k].x -= points[0].x;
                        points[k].y -= points[0].y;
                    }
                    kinds.insert(points);
                }
            }
        }
        cout << islandNums << " " << areas.size() << " " << kinds.size() << endl;
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值