第九届蓝桥杯省赛--全球变暖

版权声明:本文为博主原创文章,未经博主允许不得转载。

一、问题描述

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

  【输入格式】
    第一行包含一个整数N。  (1 <= N <= 1000)  
    以下N行N列代表一张海域照片。照片保证第1行、第1列、第N行、第N列的像素都是海洋。 
  【输出格式】
    一个整数表示答案。

  【输入样例】
    7
    .......
    .##....
    .##....
    ....##.
    ..####.
    ...###.
    .......  

  【输出样例】
    1 
  资源约定:
    峰值内存消耗(含虚拟机) < 256M
    CPU消耗  < 1000ms
  请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。
  所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
  不要使用package语句。不要使用jdk1.7及以上版本的特性。
  主类的名字必须是:Main,否则按无效代码处理。


二、题目类型:编程大题、图、DFS

三、解题思路及代码

  自己对于图的一些算法真的学得很差,意思明白,代码却写不出来。。。哭辽。。希望未来的我再次看到这篇博文时,会笑现在的自己怎么那么的蠢。。。

  这道题对于不会DFS算法的同学来说,真的就没那么容易写的出来,比如我。网上找别人的题解,大多都只是放个代码,注释都没有。。。看不懂啊哥。。

  再加上身体不适,所以博客才会断更这么久,好在,今天静下心来读代码,终于读懂了,我参考的是CSDN上爱我就像爱生命这位博主的代码。

  伪代码:

    1、把输入的“.”和“#”,换成用邻接矩阵来表示;

    2、初始化两个二维数组:map[][]、vis[][],map用来保存原始输入的海域照片数据,vis用来保存dfs遍历后的海域照片数据;

    3、一个dfs方法,用来判断一块岛屿是否会被完全淹没,以及间接计算出总的岛屿数量是多少。

  即使思路懂了,但是写代码的时候也是一波三折,巨尼玛der,靠。

 1 import java.util.Scanner;
 2 
 3 public class GlobalWarming {
 4     private static int n;
 5     private static char[][] map;// 存储原始的海域照片数据
 6     private static char[][] vis;// 存储dfs遍历后的海域照片数据
 7 
 8     public static void main(String[] args) {
 9         Scanner input = new Scanner(System.in);
10         n = input.nextInt();
11         map = new char[n][n];
12         vis = new char[n][n];
13         String[] s = new String[n];
14         for (int i = 0; i < n; i++) {
15             s[i] = input.next();
16             for (int j = 0; j < n; j++) {
17                 map[i][j] = s[i].charAt(j);
18                 vis[i][j] = s[i].charAt(j);// 不能偷懒直接把map赋值给vis,否则修改vis也就修改了map!
19             }
20         }
21         int a = 0;// 记录总的岛屿数
22         int b = 0;// 记录不会被淹没的岛屿数
23         for (int i = 0; i < n; i++) {
24             for (int j = 0; j < n; j++) {
25                 if (vis[i][j] == '#') {// 寻找岛屿的第一个陆地
26                     a++;
27                     b += dfs(i, j) ? 1 : 0;
28                 }
29             }
30         }
31         System.out.println(a - b);
32     }
33 
34     public static boolean dfs(int x, int y) {// 判断岛屿是否会被淹没以及间接计算岛屿数量
35         if (x >= vis.length || x < 0 || y >= vis.length || y < 0 || vis[x][y] == '.') // 如果越界或者是海洋就返回false
36             return false;
37         vis[x][y] = '.';// 访问过的陆地就置为海洋,直到一个岛屿都被置为海洋---剪枝
38         boolean flag = false;
39         if (map[x][y + 1] == '#' && map[x][y - 1] == '#' && map[x - 1][y] == '#' && map[x + 1][y] == '#')
40             flag = true;
41         return dfs(x, y + 1) || dfs(x, y - 1) || dfs(x - 1, y) || dfs(x + 1, y) || flag;// 剪枝
42     }
43 }

  到这里如果还没有看懂的话,请结合下图试试能不能看懂:

四、反思与总结

  对于这一类型的题目还是力不从心,希望自己可以静下心来学习,多刷点力扣,不浮躁,一步一个脚印,加油啦~

  

猜你喜欢

转载自www.cnblogs.com/crush-u-1214/p/10519871.html