#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个坐标与其第一个坐标的坐标差,如果有一个不相等,则形状不同)。

 #include <iostream>
#include <cstdio>
#include <set>
#include <vector>
#include <algorithm>
using namespace std; int N, M;//N为行数,M为列数
char map[][];//存储字符矩阵
bool visit[][];//作为标记的数组 int dx[] = {-, , , };//方向数组,为了优化dfs代码
int dy[] = {, , , -};
int area = ; int NumOfIslands = , NODAI = , NODCI;//最终NumOfIslands表示岛屿数,NODAI表示不同面积的岛屿数,
//计算过程中NumOfIslands也作为某个岛屿的编号,岛屿编号从0开始 struct position {
int x;
int y;
}; int num[];//num[i]存储了编号i岛屿的面积大小 struct position a[][];//表示最多有300个岛屿,每个岛屿最大面积为300即对应300个坐标 bool flag[]; bool cmp(struct position a, struct position b){
if(a.x != b.x)
return a.x < b.x;
else
return a.y < b.y;
} int isSame(struct position *c, struct position *d, int x, int y){//判断两个岛屿形状是否相同
int flag = ;
if(num[x] != num[y])
return ;
for(int i = ; i < num[x]; i++){
if(((c[i].x - c[].x) == (d[i].x - d[].x))&& ((c[i].y - c[].y)== (d[i].y - d[].y)))
continue;
else {
flag = ;
break;
}
}
return flag;
} void dfs(int x, int y){
a[NumOfIslands][area].x = x;//保存第NumOfIslands个岛屿第area个坐标x的值
a[NumOfIslands][area].y = y;
area++;//面积数加1
visit[x][y] = ;//标记坐标(x,y)为已访问
for(int i = ; i < ; i++){
int nx = x + dx[i];
int ny = y + dy[i];
if(nx >= && nx < N && ny >= && ny < M && map[nx][ny] == '#' && visit[nx][ny] == )
dfs(nx, ny);
}
} int main(){ set<int> v;
int i, j; cin >> N >> M;
//输入字符矩阵
for(i = ; i < N; i++)
cin >> map[i]; for(i = ; i < N; i++) {
for(j = ; j < M; j++){
if(map[i][j] == '#' && visit[i][j] == ){
area = ;//初始化某个岛屿的面积数为0
dfs(i, j);
num[NumOfIslands] = area;
v.insert(area);
NumOfIslands++;
}
}
} NODAI = v.size();//面积不同的岛屿数 NODCI = NumOfIslands; //对每个岛屿的坐标进行排序,方便比较两个岛屿形状是否相同
for(i = ; i < NumOfIslands; i++){
sort(a[i], a[i] + num[i], cmp);
} //计算形状不同的岛屿数
for(i = ; i < NumOfIslands - ; i++){
if(flag[i] == ){
continue;
}
else {
for(j = i+; j < NumOfIslands; j++) {
if((flag[j] == ) && (isSame(a[i], a[j], i, j))){
flag[j] = ;
NODCI--;
}
}
} } cout << NumOfIslands << " " << NODAI << " " << NODCI << endl;
//system("pause");
return ;
}
 

hihocoder 1310 岛屿的更多相关文章

  1. hiho #1310 : 岛屿 (dfs,hash)

    题目2 : 岛屿 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 给你一张某一海域卫星照片,你需要统计: 1. 照片中海岛的数目 2. 照片中面积不同的海岛数目 3. 照 ...

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

    思路: 并查集的应用. 实现: #include <iostream> #include <cstdio> using namespace std; ][]; int n, x ...

  3. hihocoder 1176

    hihocoder 1176 题意:N,M.分别表示岛屿数量和木桥数量,一笔画 分析:欧拉路问题(给定无孤立结点图G,若存在一条路,经过图中每边一次且仅一次,该条路称为欧拉路) 欧拉路的条件 一个无向 ...

  4. 【HIHOCODER 1176】 欧拉路·一

    描述 小Hi和小Ho最近在玩一个解密类的游戏,他们需要控制角色在一片原始丛林里面探险,收集道具,并找到最后的宝藏.现在他们控制的角色来到了一个很大的湖边.湖上有N个小岛(编号1..N),以及连接小岛的 ...

  5. 【[Offer收割]编程练习赛11 C】岛屿3

    [题目链接]:http://hihocoder.com/problemset/problem/1487 [题意] 中文题 [题解] 岛屿的数目对应了这个图中联通块的数目; 面积则对应有多少个方块; 周 ...

  6. [LeetCode] Island Perimeter 岛屿周长

    You are given a map in form of a two-dimensional integer grid where 1 represents land and 0 represen ...

  7. [LeetCode] Number of Islands II 岛屿的数量之二

    A 2d grid map of m rows and n columns is initially filled with water. We may perform an addLand oper ...

  8. [LeetCode] Number of Islands 岛屿的数量

    Given a 2d grid map of '1's (land) and '0's (water), count the number of islands. An island is surro ...

  9. hihocoder -1121-二分图的判定

    hihocoder -1121-二分图的判定 1121 : 二分图一•二分图判定 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 大家好,我是小Hi和小Ho的小伙伴Net ...

随机推荐

  1. JQuery中对Select的option项的添加、删除、取值

    jQuery获取Select选择的Text和Value: $("#select_id").change(function(){//code...}); //为Select添加事件, ...

  2. 乐观锁--CAS

    悲观锁与乐观锁的区别 悲观锁会把整个对象加锁占为已有后才去做操作,Java中的Synchronized属于悲观锁.悲观锁有一个明显的缺点就是:它不管数据存不存在竞争都加锁,随着并发量增加,且如果锁的时 ...

  3. ASP.NET MVC- Area 使用

    ASP.NET MVC允许使用 Area(区域)来组织Web应用程序,每个Area代表应用程序的不同功能模块.这对于大的工程非常有用,Area 使每个功能模块都有各自的文件夹,文件夹中有自己的Cont ...

  4. 一款多浏览器兼容的javascript多级下拉菜单

    这个多级下拉菜单的脚本大小不到2K,带有动画效果,可以方便地支持多个实例,并且能良好兼容WordPress系统wp_list_cats和wp_list_pages生成的多级列表.要初始化一个菜单,只需 ...

  5. 根据powerdesigner的OO模型生成C#代码

    2007-05-15 08:34:11|  分类: 转贴部分 |  标签:学习帖子 |字号 订阅 习惯了用Powerdesigner设计数据库模型,XDE设计类图.因此我一般的设计方法是用PD做分析模 ...

  6. C#客户端链接网页需要用到的WebClient

    WebClient 类提供向 URI 标识的任何本地.Intranet 或 Internet 资源发送数据以及从这些资源接收数据的公共方法. WebClient 类使用 WebRequest 类提供对 ...

  7. 小谈chrome调试命令:console.log的使用

    相信从事前端开发的您,一定不会陌生Mozilla五星级推荐的一款插件:firebug,它是如此强大,乃至于我们可以很方便地调试DHTML的近乎所有元素.而在它深邃的机体里,还存有一个命令:consol ...

  8. 实现经常使用的配置文件/初始化文件读取的一个C程序

    在编程中,我们常常会遇到一些配置文件或初始化文件. 这些文件通常后缀名为.ini或者.conf.能够直接用记事本打开.里面会存储一些程序參数,在程序中直接读取使用.比如,计算机与server通信.se ...

  9. Android-WizardPager

    https://github.com/HeinrichReimer/Android-WizardPager

  10. 苹果Swift语言中文教程资源汇总

    苹果swift语言中文教程(零)搭配环境以及代码执行成功http://vjiazhi.com/kaifa/1014.html 苹果Swift语言中文教程(一)基础数据类型 http://vjiazhi ...