题目描述
你有一张某海域NxN像素的照片,".“表示海洋、”#"表示陆地,如下所示:
7
…
.##…
.##…
…##.
…####.
…###.
…
其中"上下左右"四个方向上连在一起的一片陆地组成一座岛屿。例如上图就有2座岛屿。
由于全球变暖导致了海面上升,科学家预测未来几十年,岛屿边缘一个像素的范围会被海水淹没。具体来说如果一块陆地像素与海洋相邻(上下左右四个相邻像素中有海洋),它就会被淹没。
例如上图中的海域未来会变成如下样子:
…
…
…
…
…#…
…
…
请你计算:依照科学家的预测,照片中有多少岛屿会被完全淹没。
【输入格式】
第一行包含一个整数N。 (1 <= N <= 1000)
以下N行N列代表一张海域照片。
照片保证第1行、第1列、第N行、第N列的像素都是海洋。
【输出格式】
一个整数表示答案。
【输入样例】
7
. . . . . . .
. # # . . . .
. # # . . . .
. . . . # # .
. . # # # # .
. . . # # # .
. . . . . . .
【输出样例】
1
【输入样例】
5
. . . . .
. # . # .
. . # . .
. # . # .
. . . . .
【输出样例】
5
解题思路:
首先阅读题目,我们要拆分成两个问题去解决,一,如何去在海洋当中找到所有的岛屿,二,如何判断这些岛屿是否会被海水淹没,先来看第一个问题,从数据结构来看,这是矩阵求联通图,我们可以使用图的遍历,但由于数据规模的限制,为了避免内存溢出,我们选用广度优先遍历,先调用work方法遍历map海洋陆地图,去寻找陆地,一旦找到一块新陆地,我们就调用bfs去开拓寻找这一块新岛屿。每次找完一个岛屿我们都会对其标记数组进行打印以便校验结果。再来判断第二个问题,如果某一块陆地四周临海,那就一定会被淹没,所以我们在解决第一个问题的时候,就可以捎带解决第二个问题,然后用cn1来记录岛屿陆地的个数,用cn2来记录岛屿临海的陆地个数,若二者相等则必定会整个岛屿都被淹没,在sum总计求和进行累加操作。
package 蓝桥杯;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
/**
*
* @author Administrator
* 矩阵联通图 bfs
*/
public class 全球变暖 {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
char[][] map = new char[n][n];
int[][] flag = new int[n][n];
for(int i = 0;i < n;i++) {
String str = in.next();
for(int j = 0;j < n;j++) {
map[i] = str.toCharArray();
}
}
System.out.println("*****************************");
work(map,flag,n);
}
//发现陆地
public static void work(char[][] map,int[][] flag,int n) {
int sum = 0;
for(int i = 0;i < n;i++) {
for(int j = 0;j < n;j++) {
if(map[i][j] == '#' && flag[i][j] == 0) {
if(bfs(i,j,flag,map)) {
sum++;
}
//求完陆地便进行打印标记数组校验
for(int a = 0;a < n;a++) {
for(int b = 0;b < n;b++) {
System.out.print(flag[a][b] + " ");
}
System.out.println();
}
System.out.println("*****************************");
}
}
}
System.out.println(sum);
}
//遍历找出某一个岛屿
public static boolean bfs(int x,int y,int[][] flag,char[][] map) {
int[] dx = {0,1,-1,0};//右,下,上,左
int[] dy = {1,0,0,-1};
int cn1 = 0;
int cn2 = 0;
int size = flag[0].length;
Queue<land> queue = new LinkedList<land>();
land first = new land(x,y);
flag[x][y] = 1;
queue.add(first);
while(!queue.isEmpty()) {
land temp = queue.poll();
cn1++;
for(int i = 0;i < 4;i++) {
int x1 = temp.x+dx[i];
int y1 = temp.y+dy[i];
if(0 <= x1 && x1 < size && 0 <= y1 && y1 < size && map[x1][y1] == '#') {
if(check(x1,y1,flag)) {
flag[x1][y1] = 1;
land node = new land(x1,y1);
queue.add(node);
}
}
}
if(nearSea(temp.x,temp.y,map))
cn2++;
}
if(cn1 == cn2)
return true;
else
return false;
}
public static boolean check(int x,int y,int[][] flag) {
if(flag[x][y] == 0)
return true;
else
return false;
}
public static boolean nearSea(int x,int y,char[][] map) {
int[] dx = {0,1,-1,0};//右,下,上,左
int[] dy = {1,0,0,-1};
for(int i = 0;i < 4;i++) {
int x1 = x+dx[i];
int y1 = y+dy[i];
if(map[x1][y1] == '.')
return true;
}
return false;
}
}
class land{
int x;
int y;
public land(int x,int y) {
this.x = x;
this.y = y;
}
}