题目
你有一张某海域 N×N 像素的照片,”.”表示海洋、”#”表示陆地,如下所示:
....... .##.... .##.... ....##. ..####. ...###. .......
其中”上下左右”四个方向上连在一起的一片陆地组成一座岛屿,例如上图就有 2 座岛屿。
由于全球变暖导致了海面上升,科学家预测未来几十年,岛屿边缘一个像素的范围会被海水淹没。
具体来说如果一块陆地像素与海洋相邻(上下左右四个相邻像素中有海洋),它就会被淹没。
例如上图中的海域未来会变成如下样子:
....... ....... ....... ....... ....#.. ....... .......
请你计算:依照科学家的预测,照片中有多少岛屿会被完全淹没。
输入格式
第一行包含一个整数N。
以下 N 行 N 列,包含一个由字符”#”和”.”构成的 N×N 字符矩阵,代表一张海域照片,”#”表示陆地,”.”表示海洋。
照片保证第 1 行、第 1 列、第 N 行、第 N 列的像素都是海洋。
输出格式
一个整数表示答案。
数据范围
1≤N≤1000
输入样例1:
7 ....... .##.... .##.... ....##. ..####. ...###. .......
输出样例1:
1
输入样例2:
9 ......... .##.##... .#####... .##.##... ......... .##.#.... .#.###... .#..#.... .........
输出样例2:
1
思路
很明显,这是一个连通块问题,用基础搜索即可解决。bfs和dfs都可
遍历一个连通块(找到这个连通块中所有的’#‘,并标记已经搜过,不用再搜);再遍历下一个连通块…;遍历完所有连通块,统计有多少个连通块。
回到题目,什么岛屿不会被完全淹没?若岛中有个陆地(称为高地),它周围都是陆地,那么这个岛不会被完全淹没。
用DFS或BFS搜出有多少个岛(连通块),并且在搜索时统计那些没有高地的岛(连通块)的数量,就是答案。
因为每个像素点只用搜一次且必须搜一次,所以复杂度是O(n^2)。
代码
dfs
import java.util.*;
import java.io.*;class Main{static int flag; // 使用flag记录该各连通块是否被完全淹没static int ans;static int[] dx = {0,1,0,-1};static int[] dy = {1,0,-1,0};static char[][] c = new char[1010][1010];static boolean[][] st = new boolean[1010][1010]; // 标记岛屿是否被搜过static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));static int n;public static void main(String[] args) throws Exception{n = Integer.parseInt(in.readLine());for(int i=0;i<n;i++){String s = in.readLine();for(int j=0;j<n;j++)c[i][j] = s.charAt(j);}// 对每个点都要进行遍历一遍,看其是否是#且没有被搜过,那么就对这个连通块进行dfs搜索for(int i=1;i<n-1;i++){for(int j=1;j<n-1;j++){if(c[i][j]=='#'&&st[i][j]==false){flag = 0;dfs(i,j);if(flag==0) ans++; }}}System.out.println(ans);}public static void dfs(int i,int j){st[i][j] = true;if(c[i-1][j]=='#'&&c[i+1][j]=='#'&&c[i][j-1]=='#'&&c[i][j+1]=='#') //如果四周都是陆地,则表明这块连通块不会被完全淹没flag = 1;for(int k=0;k<4;k++){ // 对四周的陆地再进行处理int x = i+dx[k];int y = j+dy[k];if(x>=0&&x<n&&y>=0&&x<n&&c[x][y]=='#'&&st[x][y]==false)dfs(x,y);}return;}
}