蓝桥杯——全球变暖

标题:全球变暖

你有一张某海域NxN像素的照片,"."表示海洋、"#"表示陆地,如下所示:
.......
.##....
.##....
....##.
..####.
...###.
.......
其中"上下左右"四个方向上连在一起的一片陆地组成一座岛屿。例如上图就有2座岛屿。  
由于全球变暖导致了海面上升,科学家预测未来几十年,岛屿边缘一个像素的范围会被海水淹没。具体来说如果一块陆地像素与海洋相邻(上下左右四个相邻像素中有海洋),它就会被淹没。  

例如上图中的海域未来会变成如下样子:
.......
.......
.......
.......
....#..
.......
.......

请你计算:依照科学家的预测,照片中有多少岛屿会被完全淹没。  

【输入格式】
第一行包含一个整数N。  (1 <= N <= 1000)  

以下N行N列代表一张海域照片。  

照片保证第1行、第1列、第N行、第N列的像素都是海洋。

  【输出格式】

一个整数表示答案。

【输入样例】

.......
.##....
.##....
....##.
..####.
...###.
.......  

【输出样例】

1  


思路:dfs判断,最后处理岛的个数。

7
.......
..###..
..###..
..###..
..###..
..##...
.......

0


7
.......
..###..
..###..
..##...
..###..
..##...
.......

0

看成了求淹没后剩下的岛的数量,而题中要求的是“被淹没岛的数量”

这个代码是求剩下的岛的数量:

import java.util.Scanner;


public class 全球变暖 {


	/**
	 * 题中说:照片保证第1行、第1列、第N行、第N列的像素都是海洋
	 * 所以判断条件会简单很多
	 * @param args
	 */
	static int sum=0;
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		int n=sc.nextInt();
		int m[][]=new int[n][n];
		//将‘.’变为0,‘#’变为1(个人习惯,其实都一样)
		for (int i = 0; i < m.length; i++) {
			String s=sc.next();
			for (int k = 0; k < s.length(); k++) {
				if(s.charAt(k)=='.'){
					m[i][k]=0;
				}else {
					m[i][k]=1;
				}
			}
		}
		int vis[][]=new int[n][n];
		dfs(m,vis,0,0);
		int res=judge(vis,sum);
		System.out.println(res);
	}

	/**
	 * 判断最终的岛屿数量
	 * @param vis 水淹没之后的岛屿地图
	 * @param s 现在的岛屿由几个‘#’组成
	 * @return
	 */
	private static int judge(int[][] vis, int s) {
		int t=s;
		for (int i = 0; i < vis.length; i++) {
			for (int j = 0; j < vis[0].length; j++) {
				if(vis[i][j]==1){
					vis[i][j]=2;
					if(vis[i+1][j]==1){
						t--;
					}else if (vis[i-1][j]==1) {
						t--;
					}else if (vis[i][j-1]==1) {
						t--;
					}else if (vis[i][j+1]==1) {
						t--;
					}
				}
			}
		}
		return t;
	}    

	/**
	 * dfs水淹
	 * @param m 初始地图
	 * @param vis 记忆表
	 * @param h 行
	 * @param l 列
	 */
	private static void dfs(int[][] m, int[][] vis, int h, int l) {
		if(h==m.length){
			return;
		}
		if(m[h][l]==0){
			dfs(m,vis, h+(l+1)/m.length,(l+1)%m.length);
		}else {
			if(m[h][l]==1 && check(m,h,l)){
				sum++;
				vis[h][l]=1;
				dfs(m,vis, h+(l+1)/m.length,(l+1)%m.length);
			}else {
				dfs(m,vis, h+(l+1)/m.length,(l+1)%m.length);
			}
		}
	}
	/**
	 * 判断是否被水淹
	 * @param m
	 * @param h
	 * @param l
	 * @return
	 */
	private static boolean check(int[][] m, int h, int l) {
		if(m[h+1][l]==1 && m[h-1][l]==1 && m[h][l+1]==1 && m[h][l-1]==1){
			return true;
		}
		return false;
	}


}

正确代码,被淹的岛的数量

import java.util.HashSet;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
import java.util.Set;

public class 全球变暖_bfs {

	/**
	 * 基本是通过遍历,找到一个岛屿的开始,然后遍历整座岛屿,用vis数组加以区分
	 * 一次bfs遍历完成退出while循环 一座岛屿就遍历完成
	 * 编号自增,
	 * 根据vis[i][j]=0&&x[i][j]=1找下一个岛屿
	 * 最后list记录了所有岛屿的坐标及其属于的岛的编号sign
	 * 只需要根据vis数组找到,上下左右都是“#”的地方,然后根据编号判断被淹没的岛的数量
	 * @param args
	 */
	static class node{
		public int x;
		public int y;
		public int sign;//岛屿的编号
		node(int x,int y,int sign){
			this.x=x;
			this.y=y;
			this.sign=sign;
		}
	}
	static int num=0;//岛的总数
	static LinkedList<node> list=new LinkedList<node>();
	static int dir[][]={{-1,0},{0,1},{1,0},{0,-1}};
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		int n=sc.nextInt();
		int x[][]=new int[n][n];
		for (int i = 0; i < n; i++) {
			String s=sc.next();
			for (int j = 0; j < s.length(); j++) {
				if(s.charAt(j)=='#'){
					x[i][j]=1;
				}
			}
		}
		int vis[][]=new int[n][n];
		for (int i = 1; i < x.length; i++) {
			for (int j = 1; j < x[0].length; j++) {
				if(x[i][j]==1){//说明是陆地
					if(vis[i][j]==0){//没有被访问过
						num++;
						list.add(new node(i,j,num));//记录岛组成
						//bfs遍历这个岛并记录这个岛的编号
						bfs(x,vis);//bfs过程中会更新vis表
					}
				}
			}
		}
		Set<Integer> res=new HashSet<Integer>();//记录被淹没的到的编号
		for (int i = 0; i < list.size(); i++) {
			int xe=list.get(i).x;
			int ye=list.get(i).y;
//			System.out.println(xe+" "+ye+" "+list.get(i).sign);
			//周围是“#”说明没有被淹没
			if(vis[xe+1][ye]==2&&vis[xe-1][ye]==2&&vis[xe][ye+1]==2&&vis[xe][ye-1]==2){
//				System.out.println(xe+" x "+ye+" "+list.get(i).sign);
				res.add(list.get(i).sign);
			}
		}
		int sum=0;//被淹岛的数量
		for (int i = 1; i <= num; i++) {
			if(!res.contains(i)){
				sum++;
			}
		}
		System.out.println("幸存的岛屿编号"+res);//最后幸存的岛的编号
		System.out.println("被淹的岛数"+sum);
	}
	private static void bfs(int[][] x, int[][] vis) {
		Queue<node> q=new LinkedList<node>();
		q.offer(list.getLast());
		while (q.size()!=0) {
			node temp=q.poll();
			//这里要区分没被遍历过的地方,海,和陆地
			if(x[temp.x][temp.y]==0){//判断这个节点是海还是陆地
				vis[temp.x][temp.y]=1;//海标1
			}else {
				vis[temp.x][temp.y]=2;//陆地标2
			}
			//遍历周围节点
			for (int k = 0; k < dir.length; k++) {
				int xt=temp.x+dir[k][0];
				int yt=temp.y+dir[k][1];
				//如果这个点在范围内且不是海洋
				if(in(x,xt,yt) && vis[xt][yt]!=1){
					//如果没被遍历过且是岛屿
					if(vis[xt][yt]==0 && x[xt][yt]==1){
						q.offer(new node(xt,yt,temp.sign));
					}
					list.add(temp);
				}
			}
		}
	}
	private static boolean in(int[][] m, int x, int y) {
		if(x<=0 || x>=m.length-1 || y<=0 || y>=m[0].length-1){
			return false;
		}
		return true;
	}
}




猜你喜欢

转载自blog.csdn.net/qq_39020387/article/details/79878020