岛屿

本题来自hihocoder #1310

时间限制:10000ms
单点时限:1000ms
内存限制:256MB

描述

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

1. 照片中海岛的数目

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

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

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

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

  

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

输入

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

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

输出

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

样例输入

5 7
.####..  
.....#.  
####.#.  
.....#.  
..##.#.  

样例输出

4 2 3

分析

对于这道题,首先我们需要求出有多少个岛屿,这可以很容易地用dfs的方法求得,进行dfs的同时,我们顺便计算每个岛屿的面积以及dfs过程中经过的点的序列。这样,为了比较两个岛屿是否有相同的形状,只需要查看二者的dfs序列是否只差一个平移操作。这道题的代码如下:

#include<iostream>
#include<vector>
#include<deque>
#include<stack>
#include<string>
#include<algorithm>
#include<string.h>
#include<sstream>
#include<set>

using namespace std;


char photo[50][50];
bool is_visited[50][50];
int N, M;

const int dir[4][2] = {
    { -1, 0 },
    { 1, 0 },
    { 0, 1 },
    { 0, -1 },
};

struct island {
    int S;
    vector<int> pos_y;
    vector<int> pos_x;
};

void my_dfs(int i, int j, island& isl){
    if (i < 0 || i >= N || j < 0 || j >= M || photo[i][j] == '.' || is_visited[i][j])
        return;

    is_visited[i][j] = true;
    ++isl.S;
    isl.pos_y.push_back(i);
    isl.pos_x.push_back(j);
    for (int d = 0; d < 4; ++d){
        int i1 = i + dir[d][0];
        int j1 = j + dir[d][1];
        if (i1 >= 0 && i1 <= N && j1 >= 0 && j1 <= M)
            my_dfs(i1, j1,isl);
    }

    return;
}

void get_info(vector<island>& islands){
    for (int i = 0; i < N; ++i)
        for (int j = 0; j < M; ++j) {
            if (photo[i][j] == '#' && !is_visited[i][j]) {
                island tmp;
                tmp.S = 0;
                my_dfs(i, j, tmp);
                islands.push_back(tmp);
            }
        }
}

int dif_num_of_areas(vector<island>& islands){
    set<int> areas;
    for (int i = 0; i < islands.size(); ++i) {
        if (areas.find(islands[i].S) == areas.end())
            areas.insert(islands[i].S);
    }
    return areas.size();
}

bool shape_equal(island a, island b) {
    
    if (a.S != b.S) return false;

    int dif_y = a.pos_y[0] - b.pos_y[0];
    int dif_x = a.pos_x[0] - b.pos_x[0];
    for (int i = 0; i < a.pos_x.size(); ++i) {
        if (a.pos_y[i] - b.pos_y[i] != dif_y || a.pos_x[i] - b.pos_x[i] != dif_x)
            return false;
    }
    return true;
}

int dif_shapes(vector<island>& islands){
    vector<int> shapes;
    for (int i = 0; i < islands.size(); ++i){
        bool is_existed = false;
        for (int j = 0; j < shapes.size(); ++j){
            if (shape_equal(islands[i], islands[shapes[j]])){
                is_existed = true;
            }
        }
        if (is_existed) continue;
        shapes.push_back(i);
    }

    return shapes.size();
}


int main() {
    
    cin >> N >> M;
    for (int i = 0; i < N; ++i)
        for (int j = 0; j < M; ++j) {
            cin >> photo[i][j];
        }
    vector<island> islands;
    //vector<int> num_of_areas;
    //vector<int> shapes;

    get_info(islands);
    
    cout << islands.size() << ' ' << dif_num_of_areas(islands) << ' ' << dif_shapes(islands) << endl;

    //system("pause");

    return 0;
}

 

posted @ 2017-07-03 14:09  mhkds  阅读(223)  评论(0编辑  收藏  举报