hihoCoder1310—岛屿(搜索)

题目链接:传送门

时间限制: 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
解题思路:详细题解


#include <cstdio>  
#include <cstring>  
#include <cmath>  
#include <iostream>  
#include <queue>
#include <set>
#include <string>
#include <stack>
#include <algorithm>
#include <map>
#include <bitset>
using namespace std;  
typedef long long ll;
const int N = 60;
const int M = 1000009;
const int INF = 0x3fffffff;
const int mod = 1e9+7;
const double Pi = acos(-1.0);
const double sm = 1e-9;
typedef pair<int,int>PA;

char data[N][N];
int vis[N][N],tot,r0,c0;
int x[] = { -1 , 0 , 1 , 0 };
int y[] = { 0 , -1 , 0 , 1 };
char re[] = {'l','u','r','d'};
vector<PA>st;

bool comp(const PA&a ,const PA&b ){
	if(a.first==b.first) return a.second<b.second;
	else return a.first<b.first;
}

void dfs( int r , int c ) 
{
	++tot;
	vis[r][c] = 1;
	st.push_back(PA(r-r0,c-c0));
	for( int i = 0 ; i < 4 ; ++i ){
		int nr = r+x[i];
		int nc = c+y[i];
		if( data[nr][nc] != '#'||vis[nr][nc] != 0 ) continue;
		dfs( nr , nc );
	}
}

int main()
{
	int n,m;
	while( cin >> n >> m ){
		memset( vis , 0 , sizeof(vis) );
		memset( data , 0 , sizeof(data) );
		for( int i = 1 ; i <= n ; ++i ){
			cin >> data[i]+1;
		}
		map<vector<PA>,int>mp1;
		map<int,int>mp2;
		int cnt1=0;
		for( int i = 1 ; i <= n ; ++i ){
			for( int j = 1 ; j <= m ; ++j ){
				if( data[i][j] == '#'&& !vis[i][j] ){
					tot = 0; st.clear();
					r0 = i,c0 = j;
					dfs(i,j);
					sort(st.begin(),st.end(),comp);
					++cnt1;
					++mp2[tot];
					++mp1[st];
				}
			}
		}
		cout << cnt1 << " " << mp2.size() << " " << mp1.size() << endl;
	}
	return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值