蓝桥杯:全球变暖

目录

题目描述

输入描述

输入输出样例:

 题目分析:(DFS)

AC代码(Java):


题目描述

你有一张某海域 NxN像素的照片,"."表示海洋、"#"表示陆地,如下所示:

.......

.##....

.##....

....##.

..####.

...###.

.......

其中"上下左右"四个方向上连在一起的一片陆地组成一座岛屿。例如上图就有 2 座岛屿。

由于全球变暖导致了海面上升,科学家预测未来几十年,岛屿边缘一个像素的范围会被海水淹没。具体来说如果一块陆地像素与海洋相邻(上下左右四个相邻像素中有海洋),它就会被淹没。

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

.......

.......

.......

.......

....#..

.......

.......

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

输入描述

第一行包含一个整数 N(1≤N≤1000)。

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

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

输出一个整数表示答案。

输入输出样例:

输入

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

输出

1

 题目分析:(DFS)

        蓝桥杯(阅读理解杯),首先要看明白题目的要求

        1.给的是一个图,“.”表示海水,"#"表示陆地,根据题目要求,其实只有两种情况,海水和陆地,那么可以考虑用boolean来存放,false为海水,true为陆地

        2.什么是岛屿?一块陆地也可以算一座岛屿,只要它四周都是海水,相连的陆地,周围是海水,那么也只算一块岛屿,明白了这个,再继续往下看

        3.如果一个陆地 上下左右 都是陆地,那么它就肯定不会被淹没。按照这个来看,我们可以把这块陆地叫做 “山”。因为不是山的陆地,周围肯定有海水,按照题目来说,就是肯定会被淹没。

        4.有一种情况(error了两次,就是因为没考虑这个),也就是一块岛屿,被淹没之后,有可能变成了两块岛屿,所以先求所有的岛屿数量,在将这些岛屿进行淹没处理,在计算剩余岛屿数量是行不通的。既然这样,那我们可以换一个思路,我们先拿到图,复制一份,将图中为山的坐标记为true,其余都是海水,然后原始的那张图就正常记录(false是海水,true是陆地),然后遇到陆地,就dfs搜索该块陆地(row,col),如果这块陆地没有和山相连,那么这块岛屿(因为要搜索与这块陆地相连的部分,也可以将这块陆地叫做岛屿,当然,如果这块陆地周围都是水,那么也可以叫做岛屿)中没有山,那么这块岛屿肯定会被沉没,那么我们就返回true,然后记录淹没数量。

        5.具体代码每一步我都写有注释,如果不明白可以讨论区提问,我看到就会回~

AC代码(Java):

import java.util.Scanner;
// 1:无需package
// 2: 类名必须Main, 不可修改

public class Main {
    //创建两个boolean数组,用来存放海域状态(因为海域就只可能有两种状态,海水和陆地),节省空间
    static boolean[][] target,result;
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int N = sc.nextInt();
        //target存放海域初始状态
        target = new boolean[N][N];
        for(int row = 0;row<N;row++){
            String str = sc.next();
            char[] chs = str.toCharArray();
            for(int col = 0;col<N;col++){
                //如果当前位置是陆地,我们就记为true,否则记为false
                if(chs[col]=='#'){
                    target[row][col] = true;
                }else{
                    target[row][col] = false;
                }
            }
        }
        //result只存放海域中不会被淹没的陆地(即上下左右都是陆地),也可以叫做’山‘
        result = new boolean[N][N];
        for(int row = 0;row<N;row++){
            for(int col = 0;col<N;col++){
                //先判断该坐标是否为陆地,如果是陆地,在判断是不是'山'
                if(target[row][col]){
                    //因为第一行,第一列,第N行,第N列都是. 也就是false,所以不用担心越界
                    //山的条件是 上下左右都是陆地,所以一次性写上
                    if( target[row-1][col] && target[row+1][col] && target[row][col-1] && target[row][col+1]){
                        //如果上下左右都是陆地,那么我们就记为'山',也就是true
                        result[row][col] = true;
                    }else{
                        //不是山的肯定会被淹没,所以直接当海水处理
                        result[row][col] = false;
                    }
                }
            }
        }
        //处理完,现在有了目标海域(target,用来计算非山的陆地数量,也就是沉没的陆地数量)和结果海域(result,记录不会沉没的陆地信息)
        //我们dfs搜索目标海域,如果遇到陆地,就判断陆地里面有没有山,有山,代表这一部分的陆地都不会沉没完,也就不符合题目要求的完全沉没的岛屿
        int number = 0;//记录被淹没的岛屿数量
        for(int row = 0;row<N;row++){
            for(int col = 0;col<N;col++){
                //先判断当前坐标是否为陆地,如果为陆地(true),那么就搜索
                if(target[row][col]){
                    //以row,col为坐标起点,搜索周围相连的陆地,并把他们修改为海水
                    if(dfs(row,col)){
                        //搜索完之后,如果是true,那么代表搜索的区域都没有 山 ,那么这区域肯定是要被淹没的岛屿
                        number++;
                    }
                }
            }
        }
        //输出被淹没的岛屿数量
        System.out.println(number);
        sc.close();
    }
    /**
     * 用来搜索给定坐标内的所有陆地(也就是这块岛屿),是否有山,如果有山,那么代表这块岛屿都不会被淹没,也就是返回false
     * 如果这块岛屿内没有山,那么肯定会被淹没,就返回true进行计数
     * */
    private static boolean dfs(int row, int col) {
        //默认周围没有'山'
        boolean isEmpty = true;
        //将当前坐标修改为海水
        target[row][col] = false;
        //然后判断当前坐标是不是山,如果是’山‘,那么就修改是否存在山的情况
        if(result[row][col]){
            isEmpty = false;
        }
        //不管是否存在有山的情况,都需要继续搜索周围为陆地的坐标,
        //然后将他们淹没(同时判断他们是否为山,所以当前坐标为'山'那么没有直接return),
        //不然后续会遍历到,并且当成一个新的岛屿
        //因为第一行,第一列,第N行,第N列都是. 也就是false,所以不用担心越界
        if(target[row-1][col]){
            //如果上是陆地,那么就淹没这块陆地
            //需要递归判断搜索的地方是不是山,如果是山,那么最终的返回结果也肯定是false;
            isEmpty = isEmpty & dfs(row-1,col);
        }
        if(target[row+1][col]){
            //下
            isEmpty = isEmpty & dfs(row+1,col);
        }
        if(target[row][col-1]){
            //左
            isEmpty = isEmpty & dfs(row,col-1);
        }
        if(target[row][col+1]){
            //右
            isEmpty = isEmpty & dfs(row,col+1);
        }
        //返回搜索之后的结果(如果这一块搜索的区域有山,那么就肯定是false)
        return isEmpty;
    }
}

 

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值