题目描述
你有一张某海域 NxN 像素的照片,"."表示海洋、"#"表示陆地,如下所示:
.......
.##....
.##....
....##.
..####.
...###.
.......
其中"上下左右"四个方向上连在一起的一片陆地组成一座岛屿。例如上图就有 2 座岛屿。
由于全球变暖导致了海面上升,科学家预测未来几十年,岛屿边缘一个像素的范围会被海水淹没。具体来说如果一块陆地像素与海洋相邻(上下左右四个相邻像素中有海洋),它就会被淹没。
例如上图中的海域未来会变成如下样子:
.......
.......
.......
.......
....#..
.......
.......
请你计算:依照科学家的预测,照片中有多少岛屿会被完全淹没。
输入描述
第一行包含一个整数 N (1≤N≤1000)。
以下 N 行 N 列代表一张海域照片。
照片保证第 1 行、第 1 列、第 N 行、第 N 列的像素都是海洋。、
输出一个整数表示答案。
输入输出样例
7
.......
.##....
.##....
....##.
..####.
...###.
.......
输出
1
这是一道基本连通性问题。算法的方案就是遍历一个连通块,找到这个连通块中所有的#,并标记为搜过,以后不再搜索。接下来在遍历下一个连通块,直到遍历完所有连通块,统计有多少个连通块。
用暴力搜索解决连通性问题,逐个搜索连通块上的所有点,每个点只搜索一次,实现这种简单的暴力搜索,BFS和DFS都可以,不仅很容易搜索到所有点,而且每个点只搜索一次。
什么岛屿不会被完全淹没呢?若岛中有一块地(高地),它周围都是陆地,那么这个岛屿不会被淹没。用DFS或者BFS搜索出有多少个岛(连通块),检查这个岛有没有高地,统计那些没有高地的岛屿数量就是答案。
DFS搜索所有点,若遇到#,就继续搜索它周围的#。把搜索过的#标记为已经搜索过,不用再搜索,统计那些没有高地的岛的数量,就是答案。搜索的时候应该判断是不是出了边界。照片保证第 1 行、第 1 列、第 N 行、第 N 列的像素都是海洋。那么就不用判断边界了,到了边界,发现是水,会停止搜索。
import java.util.Scanner;
public class mian1 {
static int N=1001;
static int visit[][]=new int[N][N];
static int dir[][]=new int[][] {{-1,0},{1,0},{0,-1},{0,1}};
static int flag=0;
static void dfs(char map[][],int x,int y) {
visit[x][y]=1;//走过
if(map[x][y+1]=='#'&&map[x][y-1]=='#'&&map[x+1][y]=='#'&&map[x-1][y]=='#') {
flag=1;
}
for (int i = 0; i < 4 ; i++) {
int nx=x+dir[i][0];
int ny=y+dir[i][1];
if(visit[nx][ny]==0&&map[nx][ny]=='#') {
dfs(map,nx,ny);
}
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc = new Scanner(System.in);
int num=sc.nextInt();
char map[][]=new char[num][num];
for (int i = 0; i < num; i++) {
map[i]=(sc.next()).toCharArray();
}
int ans=0;
for (int i = 1; i < num-1; i++) {
for (int j = 1; j < num-1; j++) {
if(visit[i][j]==0&&map[i][j]=='#') {
flag=0;
dfs(map,i,j);
if(flag==0) {
ans++;
}
}
}
}
System.out.println(ans);
}
}