hihocoder 1310 岛屿

#1310 : 岛屿

时间限制:10000ms

单点时限:1000ms

内存限制:256MB

描述

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

1. 照片中海岛的数目

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

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

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

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

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

输入

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

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

输出

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

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

思路:(1)求岛屿数目很简单,初始化岛屿数目NumOfIslands为0,遍历所有的点,如果这个点未访问并且为‘#’,则NumOfIslands++,进行DFS搜索,将和这个点属于同一个岛屿的所有为‘#‘的点标记为已访问。

(2)求解一个岛屿时,计算它的面积,将所有的面积保存下来,去掉重复元素,剩下元素个数即为面积不同的岛屿数。

(3)DFS搜索出所有岛屿,同时把每个岛屿包含的像素坐标也保存起来并按照坐标排序(先根据x从小到大排序,如果x坐标相同,再根据y从小到大排序)。  形状相同的岛屿数目我们可以通过逐一比较岛屿的每一个像素得到。当我们比较岛屿x和岛屿y时,如果每对像素的坐标差都相同,那么x和y的形状就是相同的。(首先如果两个岛屿的面积数不同,形状肯定不同,再根据岛屿x的第i(1 <= i <= 面积-1)个坐标与其第一个坐标的坐标差 ?= 岛屿y的第i个坐标与其第一个坐标的坐标差,如果有一个不相等,则形状不同)。

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <set>
  4 #include <vector>
  5 #include <algorithm>
  6 using namespace std;
  7
  8 int N, M;//N为行数,M为列数
  9 char map[55][55];//存储字符矩阵
 10 bool visit[55][55];//作为标记的数组
 11
 12 int dx[4] = {-1, 0, 1, 0};//方向数组,为了优化dfs代码
 13 int dy[4] = {0, 1, 0, -1};
 14 int area = 0;
 15
 16 int NumOfIslands = 0, NODAI = 0, NODCI;//最终NumOfIslands表示岛屿数,NODAI表示不同面积的岛屿数,
 17 //计算过程中NumOfIslands也作为某个岛屿的编号,岛屿编号从0开始
 18
 19 struct position {
 20     int x;
 21     int y;
 22 };
 23
 24 int num[300];//num[i]存储了编号i岛屿的面积大小
 25
 26 struct position a[300][300];//表示最多有300个岛屿,每个岛屿最大面积为300即对应300个坐标
 27
 28
 29 bool flag[300];
 30
 31 bool cmp(struct position a, struct position b){
 32     if(a.x != b.x)
 33         return a.x < b.x;
 34     else
 35         return a.y < b.y;
 36 }
 37
 38 int isSame(struct position *c, struct position *d, int x, int y){//判断两个岛屿形状是否相同
 39     int flag = 1;
 40     if(num[x] != num[y])
 41         return 0;
 42     for(int i = 1; i < num[x]; i++){
 43         if(((c[i].x - c[0].x) == (d[i].x - d[0].x))&& ((c[i].y - c[0].y)== (d[i].y - d[0].y)))
 44             continue;
 45         else {
 46             flag = 0;
 47             break;
 48         }
 49     }
 50     return flag;
 51 }
 52
 53 void dfs(int x, int y){
 54     a[NumOfIslands][area].x = x;//保存第NumOfIslands个岛屿第area个坐标x的值
 55     a[NumOfIslands][area].y = y;
 56     area++;//面积数加1
 57     visit[x][y] = 1;//标记坐标(x,y)为已访问
 58     for(int i = 0; i < 4; i++){
 59         int nx = x + dx[i];
 60         int ny = y + dy[i];
 61         if(nx >= 0 && nx < N && ny >= 0 && ny < M && map[nx][ny] == ‘#‘ && visit[nx][ny] == 0)
 62             dfs(nx, ny);
 63     }
 64 }
 65
 66 int main(){
 67
 68     set<int> v;
 69     int i, j;
 70
 71     cin >> N >> M;
 72     //输入字符矩阵
 73     for(i = 0; i < N; i++)
 74         cin >> map[i];
 75
 76     for(i = 0; i < N; i++) {
 77         for(j = 0; j < M; j++){
 78             if(map[i][j] == ‘#‘ && visit[i][j] == 0){
 79                 area = 0;//初始化某个岛屿的面积数为0
 80                 dfs(i, j);
 81                 num[NumOfIslands] = area;
 82                 v.insert(area);
 83                 NumOfIslands++;
 84             }
 85         }
 86     }
 87
 88     NODAI = v.size();//面积不同的岛屿数
 89
 90     NODCI = NumOfIslands;
 91
 92     //对每个岛屿的坐标进行排序,方便比较两个岛屿形状是否相同
 93     for(i = 0; i < NumOfIslands; i++){
 94         sort(a[i], a[i] + num[i], cmp);
 95     }
 96
 97     //计算形状不同的岛屿数
 98     for(i = 0; i < NumOfIslands - 1; i++){
 99         if(flag[i] == 1){
100             continue;
101         }
102         else {
103             for(j = i+1; j < NumOfIslands; j++) {
104                 if((flag[j] == 0) && (isSame(a[i], a[j], i, j))){
105                     flag[j] = 1;
106                     NODCI--;
107                 }
108             }
109         }
110
111     }
112
113     cout << NumOfIslands << " " << NODAI << " " << NODCI << endl;
114     //system("pause");
115     return 0;
116 }
 
时间: 2024-11-03 21:44:16

hihocoder 1310 岛屿的相关文章

hiho #1310 : 岛屿 (dfs,hash)

题目2 : 岛屿 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 给你一张某一海域卫星照片,你需要统计: 1. 照片中海岛的数目 2. 照片中面积不同的海岛数目 3. 照片中形状不同的海盗数目 其中海域的照片如下,"."表示海洋,"#"表示陆地.在"上下左右"四个方向上连在一起的一片陆地组成一座岛屿. .####.. .....#. ####.#. .....#. ..##.#. 上图所示的照片中一共有4座岛屿:其中

hihocoder #1487 : 岛屿3

面积  +1    周长  看旁边与之相邻的有几个 cnt   增加的变长  4-cc - cc 岛屿数目是否增加的话用并查集维护了 #include<cstdio> #include<cstring> #include<map> #include<iostream> #include<algorithm> #include<math.h> #include<map> #include<queue> #incl

hihocoder offer收割编程练习赛11 C 岛屿3

思路: 并查集的应用. 实现: 1 #include <iostream> 2 #include <cstdio> 3 using namespace std; 4 5 bool a[1005][1005]; 6 int n, x, y; 7 int par[1000005]; 8 int ran[1000005]; 9 int dx[4] = { 1, 0, -1, 0 }; 10 int dy[4] = { 0, 1, 0, -1 }; 11 12 void init(int

hihocoder 1038

http://hihocoder.com/problemset/problem/1138 题意:有一些岛屿,要从第一个岛屿到第N个岛屿,求最短距离,距离为min(x,y),也就是两个点的X的差值和Y的差值的较小的. 思路:最开始我觉得应该dijstrak可以解决,因为是LEVEL1的,结果超时了,我就想是不是head+dijstrak..结果是的,不过这个题可以用SPFA做 优化的部分也就是说对于每一个点,拓展4个边就可以,就是x差值最小的两个点,和y差值最小的两个点. 1 #include <

hihocoder 1176

hihocoder 1176 题意:N,M.分别表示岛屿数量和木桥数量,一笔画 分析:欧拉路问题(给定无孤立结点图G,若存在一条路,经过图中每边一次且仅一次,该条路称为欧拉路) 欧拉路的条件 一个无向图存在欧拉路当且仅当该图是连通 且只有2个点的度数是奇数(此时这两个点只能作为欧拉路径的起点和终点 用并查集判断第一个条件 第二个直接用数组存 1 #include <iostream> 2 #include <cmath> 3 #include <cstdio> 4 #i

[hihoCoder#1381]Little Y&#39;s Tree

[hihoCoder#1381]Little Y's Tree 试题描述 小Y有一棵n个节点的树,每条边都有正的边权. 小J有q个询问,每次小J会删掉这个树中的k条边,这棵树被分成k+1个连通块.小J想知道每个连通块中最远点对距离的和. 这里的询问是互相独立的,即每次都是在小Y的原树上进行操作. 输入 第一行一个整数n,接下来n-1行每行三个整数u,v,w,其中第i行表示第i条边边权为wi,连接了ui,vi两点. 接下来一行一个整数q,表示有q组询问. 对于每组询问,第一行一个正整数k,接下来一

hihoCoder 1175:拓扑排序二

题目链接: http://hihocoder.com/problemset/problem/1175 题目难度:一星级(简单题) 今天闲来无事,决定刷一道水题.结果发现这道水题居然把我卡了将近一个钟头. 最后终于调通了.总结起来,原因只有一个:不够仔细. 思路不用细说了,就是拓扑排序的简单应用.然而,一些不起眼的细节才是让你掉坑里的真正原因. 猜猜哪儿可能出bug? // A simple problem, but you can't be too careful with it. #inclu

东方14模拟赛之岛屿

02:岛屿 查看 提交 统计 提问 总时间限制:  40000ms 单个测试点时间限制:  4000ms 内存限制:  128000kB 描述 从前有一座岛屿,这座岛屿是一个长方形,被划为N*M的方格区域,每个区域都有一个确定的高度.不幸的是海平面开始上涨,在第i年,海平面的高度为t[i].如果一个区域的高度小于等于海平面高度,则视为被淹没.那些没有被淹没的连通的区域够成一个连通块.现在问第i年,这样的连通块有多少个. 例如:第一年海平面高度为1,有2个连通块. 第二年海平面高度为2,有3个连通

hihocoder [Offer收割]编程练习赛18 C 最美和弦(dp)

题目链接:http://hihocoder.com/problemset/problem/1532 题解:一道基础的dp,设dp[i][j][k][l]表示处理到第几个数,当前是哪个和弦错了几次初始x值是多少.这里还要再辅助一个val[k]表示处理到当前情况只错了k次的最小值是多少因为改变的不止是和弦还有初始值,可以看一下代码理解一下. #include <iostream> #include <cstring> #include <cstdio> #include &