给定一幅地图,其中有水域,有陆地。被水域完全环绕的陆地是岛屿。有些岛屿上埋藏有宝藏,这些有宝藏的点也被标记出来了。本题就请你统计一下,给定的地图上一共有多少岛屿,其中有多少是有宝藏的岛屿。
输入格式:
输入第一行给出 2 个正整数 N N N 和 M M M ( 1<N×M≤105 ),是地图的尺寸,表示地图由 N N N 行 M M M 列格子构成。随后 N N N 行,每行给出 M M M 位个位数,其中 0 表示水域,1 表示陆地,2-9 表示宝藏。
注意:两个格子共享一条边时,才是“相邻”的。宝藏都埋在陆地上。默认地图外围全是水域。
输出格式:
在一行中输出 2 个整数,分别是岛屿的总数量和有宝藏的岛屿的数量。
输入样例:10 11 01000000151 11000000111 00110000811 00110100010 00000000000 00000111000 00114111000 00110010000 00019000010 00120000001
输出样例:
7 2
解题思路:
题目给出的范围 1<N×M≤105 可以看出 N N N 和 M M M 的范围是不一定是一样的,那么我的想法就是有多少行就有多少个字符串,都存在 vector 里。然后就是熟悉的BFS了,先在主函数遍历里找是岛屿的坐标(字符不为’0’的),利用BFS遍历岛屿并且判断其中有无宝藏。岛屿的总数量就是在主函数找到未访问岛屿的次数,宝藏岛屿数量就看BFS遍历的每个岛屿中含有宝藏(一个或多个)的次数。
#include <bits/stdc++.h>
using namespace std;
int n, m;
typedef pair<int, int> PII;
map<PII, bool> vis;
vector<string> mp;
//判断坐标位置是否是岛屿且未被访问
bool judge(int x, int y)
{
if((x>=0&&x<n) && (y>=0&&y<m) && mp[x][y]-'0' && !vis[{x, y}])
return true;
return false;
}
int dx[] = {0, 1, -1, 0};
int dy[] = {1, 0, 0, -1};
int bfs(int a, int b)
{
queue<PII> q;
q.push({a, b});
vis[{a, b}] = true;
bool have=false;
while(q.size())
{
int x = q.front().first;
int y = q.front().second;
q.pop();
//判断当前岛屿坐标是否为宝藏
if(mp[x][y]>='2' && mp[x][y]<='9') have = true;
for(int i=0; i<4; i++)
{
int nx = x+dx[i];
int ny = y+dy[i];
if(judge(nx, ny))
{
vis[{nx, ny}] = true;
q.push({nx, ny});
}
}
}
if(have) return 1;
return 0;
}
int main()
{
cin>>n>>m;
getchar();
for(int i=0; i<n; i++)
{
string s;
getline(cin, s);
mp.push_back(s);
}
int cnt = 0, val = 0;
for(int i=0; i<n; i++)
{
for(int j=0; j<m; j++)
{
//找未被访问的岛屿坐标
if(!(mp[i][j]-'0') || vis[{i, j}]) continue;
val += bfs(i, j);
cnt++;
}
}
cout<<cnt<<' '<<val;
return 0;
}