蓝桥杯 全球变暖(Java)

题目描述

你有一张某海域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;
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值