1.题目
你有一张某海域 N×N像素的照片,”.”表示海洋、”#”表示陆地,如下所示:
.......
.##....
.##....
....##.
..####.
...###.
.......
其中”上下左右”四个方向上连在一起的一片陆地组成一座岛屿,例如上图就有 2座岛屿。
由于全球变暖导致了海面上升,科学家预测未来几十年,岛屿边缘一个像素的范围会被海水淹没。
具体来说如果一块陆地像素与海洋相邻(上下左右四个相邻像素中有海洋),它就会被淹没。
例如上图中的海域未来会变成如下样子:
.......
.......
.......
.......
....#..
.......
.......
请你计算:依照科学家的预测,照片中有多少岛屿会被完全淹没。
输入格式
第一行包含一个整数N。
以下 N 行 N列,包含一个由字符”#”和”.”构成的 N×N 字符矩阵,代表一张海域照片,”#”表示陆地,”.”表示海洋。
照片保证第 1行、第 1 列、第 N行、第 N 列的像素都是海洋。
输出格式
一个整数表示答案。
数据范围
1
≤
N
≤
1000
1≤N≤1000
1≤N≤1000
输入样例1:
7
.......
.##....
.##....
....##.
..####.
...###.
.......
输出样例1:
1
输入样例2:
9
.........
.##.##...
.#####...
.##.##...
.........
.##.#....
.#.###...
.#..#....
.........
输出样例2:
1
2.基本思想
BFS
- 遍历所有未遍历过的陆地,通过
bfs
计算出当前位置连通陆地的数量total
,以及被淹没陆地的数量bound
,若total == bound
表示完整淹没的一个岛屿
3.代码实现
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
public class Main { // flood fill
static Scanner sc = new Scanner(System.in);
static int N = 1010;
static char g[][] = new char[N][N];
static int[] dx = {0, 0, 1, -1}, dy = {1, -1, 0, 0};//四个方向的偏移量
static boolean st[][] = new boolean[N][N];
static int n = 0;
static class PII {//保存坐标
int x, y;
public PII(int x, int y) {
this.x = x;
this.y = y;
}
}
public static void main(String[] args) {
n = sc.nextInt();
for (int i = 0; i < n; i++) {//处理输入
char[] c = sc.next().toCharArray();
for (int j = 0; j < n; j++) {
g[i][j] = c[j];
}
}
int cnt = 0;//统计结果
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (!st[i][j] && g[i][j] == '#') {//当前位置没访问过 且 以该陆地进行 宽搜
if (bfs(i, j)) cnt++;
}
}
}
System.out.println(cnt);
}
private static boolean bfs(int x, int y) {
int total = 0, bound = 0;//当前位置连通陆地的数量 被淹没陆地的数量
Queue<PII> queue = new LinkedList<>(); //初始化 队列
queue.offer(new PII(x, y));//加入队列
st[x][y] = true;//当前点 标记访问过
while (!queue.isEmpty()) {//队列非空
PII t = queue.poll();//取出头节点 并删除
total++;
boolean is_bound = false;//判断 岛屿 是否被淹没
for (int i = 0; i < 4; i++) {
int a = t.x + dx[i], b = t.y + dy[i];//拓展四个方向的点
if (a < 0 && a >= n && b < 0 && b >= n) continue;//超出边界
if (st[a][b]) continue;//已访问过
if (g[a][b] == '.') {
is_bound = true;
continue;
}
queue.add(new PII(a, b));
st[a][b] = true;
}
if (is_bound) bound++;//拓展四个方向后 发现有与 海相连
}
return total == bound;
}
}