你有一张某海域NxN像素的照片,".“表示海洋、”#"表示陆地,如下所示:
…
.##…
.##…
…##.
…####.
…###.
…
其中"上下左右"四个方向上连在一起的一片陆地组成一座岛屿。例如上图就有2座岛屿。
由于全球变暖导致了海面上升,科学家预测未来几十年,岛屿边缘一个像素的范围会被海水淹没。具体来说如果一块陆地像素与海洋相邻(上下左右四个相邻像素中有海洋),它就会被淹没。
例如上图中的海域未来会变成如下样子:
…
…
…
…
…#…
…
…
请你计算:依照科学家的预测,照片中有多少岛屿会被完全淹没。
输入
第一行包含一个整数N。 (1 <= N <= 1000)
以下N行N列代表一张海域照片。
照片保证第1行、第1列、第N行、第N列的像素都是海洋。
输出
一个整数表示答案。
样例输入
7
…
.##…
.##…
…##.
…####.
…###.
…
样例输出
1
强调一件让自己从小到大都因为这件事懊悔的事情:读题!!!!!读题!!!!!!读题!!!!!
第一眼,以为让我求淹没后的地图长啥样,第二眼以为让我求还剩几个#,最后最后,当我看了题解才知道是求淹没了几个岛屿!!!!!!!救命!!!!!!!
无论哪个我都是第一眼有思路的。求淹没了几个岛屿,求呗,遍历地图,只要是四周又水,也就是被淹没的(或者说不是#,因为被淹没变成了水的)我就用book数组标记为0,遍历完地图后,我再遍历book数组,只要是1就表示改点还是岛屿,计数器+1,然后dfs,找与其联通的,把与它相连的都变为0.最后输出计数器个数。
这个思路也没啥大问题呀。
import java.util.Scanner;
public class t91 {
static char[][] map;
static int[][] book;
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
scanner.nextLine();
map = new char[n][n];
book = new int[n][n];
for (int i = 0; i < n; i++) {
String temp = scanner.nextLine();
char[] temp0 = temp.toCharArray();
for (int j = 0; j < n; j++) {
map[i][j] = temp0[j];
// book[i][j] = 1;
}
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (map[i][j] == '#') {
book[i][j] = 1;
if (check(i, j)) {
book[i][j] = 0;
}
}
}
}
int sum = 0;
// for (int i = 0; i < book.length; i++) {
// for (int j = 0; j < book.length; j++) {
// if (book[i][j] == 1) {
// sum++;
// }
// }
// }
// System.out.println(sum);
for (int i = 0; i < book.length; i++) {
for (int j = 0; j < book.length; j++) {
if (book[i][j] == 1) {
sum++;
dfs(i, j);
}
}
}
System.out.println(sum);
}
private static void dfs(int i, int j) {
// TODO Auto-generated method stub
int[][] dire = { { 0, 1 }, { 0, -1 }, { 1, 0 }, { -1, 0 } };
for (int k = 0; k < 4; k++) {
int x = i + dire[k][0];
int y = j + dire[k][1];
if (book[x][y] == 1) {
book[x][y] = 0;
dfs(x, y);
}
}
}
private static boolean check(int i, int j) {
// TODO Auto-generated method stub
int[][] dire = { { 0, 1 }, { 0, -1 }, { 1, 0 }, { -1, 0 } };
for (int k = 0; k < 4; k++) {
int x = i + dire[k][0];
int y = j + dire[k][1];
if (map[x][y] == '.') {
return true;
}
}
return false;
}
}
但是提交显示运行错误。
另一种解法:
dfs,其实涉及到求联通块
遍历地图,每次找到一个#,我们就dfs进入,深入寻找,也就是找连通块,在这个过程中我们同时判断是否有一个#,四周都没有海水,也就是不会淹没,那么我们可以记录,如果存在说明他不会淹没,如果不存在说明他会淹没,计数器+1,不要忘了把走过的设置为已走。
上面是思路,具体实现细节有好多方法,我看到一个是设置了ans数组,ans[i]表示第i个连通块不会被淹没的#的个数,遍历完地图后,再遍历ans,只要ans值为0,就有一个岛屿被完全淹没了,计数器加1.
import java.util.Scanner;
public class jt9 {
static char[][] map;
static int[][] book;
static int[] ans;
static int num = 0;
static int n = 0;
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
n = scanner.nextInt();
scanner.nextLine();
map = new char[n][n];
book = new int[n][n];
ans = new int[n * n];
for (int i = 0; i < n; i++) {
String temp = scanner.nextLine();
char[] temp0 = temp.toCharArray();
// ans[i] = -1;
for (int j = 0; j < n; j++) {
map[i][j] = temp0[j];
// book[i][j] = 1;
}
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (map[i][j] == '#' && book[i][j] == 0) {
dfs(i, j);
num++;
}
}
}
int sum = 0;
for (int i = 0; i < num; i++) {
if (ans[i] == 0) {
sum++;
}
}
System.out.println(sum);
}
private static void dfs(int i, int j) {
book[i][j] = 1;
int[][] dire = { { 0, 1 }, { 0, -1 }, { 1, 0 }, { -1, 0 } };
int flag = 0;
for (int k = 0; k < 4; k++) {
int x = i + dire[k][0];
int y = j + dire[k][1];
if (x >= 0 && y >= 0 && x < n && y < n && map[x][y] == '.') {
flag = 1;
}
}
if (flag == 0)
ans[num]++;
for (int k = 0; k < 4; k++) {
int x = i + dire[k][0];
int y = j + dire[k][1];
if (x >= 0 && y >= 0 && x < n && y < n && map[x][y] == '#' && book[x][y] == 0) {
dfs(x, y);
}
}
}
}
上面代码仅供参考,没有通过,显示运行错误,求指教,实在挑不出来了!!!!!!!!