版权声明:本文为博主原创文章,未经博主允许不得转载。
一、问题描述
你有一张某海域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 }
到这里如果还没有看懂的话,请结合下图试试能不能看懂:
四、反思与总结
对于这一类型的题目还是力不从心,希望自己可以静下心来学习,多刷点力扣,不浮躁,一步一个脚印,加油啦~