题目:
标题:全球变暖你有一张某海域NxN像素的照片,"."表示海洋、"#"表示陆地,如下所示:
.......
.##....
.##....
....##.
..####.
...###.
.......其中"上下左右"四个方向上连在一起的一片陆地组成一座岛屿。例如上图就有2座岛屿。
由于全球变暖导致了海面上升,科学家预测未来几十年,岛屿边缘一个像素的范围会被海水淹没。具体来说如果一块陆地像素与海洋相邻(上下左右四个相邻像素中有海洋),它就会被淹没。
例如上图中的海域未来会变成如下样子:
.......
.......
.......
.......
....#..
.......
.......请你计算:依照科学家的预测,照片中有多少岛屿会被完全淹没。
【输入格式】
第一行包含一个整数N。 (1 <= N <= 1000)
以下N行N列代表一张海域照片。照片保证第1行、第1列、第N行、第N列的像素都是海洋。
【输出格式】
一个整数表示答案。【输入样例】
7
.......
.##....
.##....
....##.
..####.
...###.
.......【输出样例】
1资源约定:
峰值内存消耗(含虚拟机) < 256M
CPU消耗 < 1000ms
请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
不要使用package语句。不要使用jdk1.7及以上版本的特性。
主类的名字必须是:Main,否则按无效代码处理。
参考解释:https://blog.youkuaiyun.com/memeda1141/article/details/80232137比较详细。
参考原文:http://www.cnblogs.com/flightless/p/8718443.html
思路:
首先,我们要判断有多少个岛屿,那么可以用两个for进行遍历,遇到第一个'#'的时候,则为存在一个岛屿。
为了方便统计,我们可以把像素点分为可淹没点和不可淹没点,如果像素点的"上下左右"四个方向上都是陆地‘#’,则是 不可淹没点,否则为可淹没点。
如题目所有样例:
.......
.##....
.##....
....##.
..####.
...###.
.......
若干年后:
.......
.......
.......
.......
....#..
.......
.......
我们可以看到,红色的‘#’上下左右都是‘#’,肯定是不可淹没的点。
求解:
public class 全球变暖 {
static char[][] map = new char[110][110]; //存储海域NxN像素
static int[] ans = new int[11000]; //记录岛屿数量
static boolean[][] vis = new boolean[110][110]; //像素访问标识,初始化所有的点都是 未被访问的
static void dfs(int x, int y, int n,int k) { //x:行,y:列,n:行列数,k:岛屿数目
if(map[x][y]=='.') //如果是海洋,不进行判断
return;
if(vis[x][y]) //如果当前像素已经被访问,跳过
return;
vis[x][y] = true; //置为被访问状态
if(x>=0 && x<n && y>=0 && y<n) //防止数组越界
if(map[x-1][y]=='#' && map[x+1][y]=='#' && map[x][y-1]=='#' && map[x][y+1]=='#') //"上下左右"四个方向上都是陆地‘#’,则是 不可淹没点,否则为可淹没点
ans[k]++; //不可淹没点+1
//进行四个方向dfs遍历
dfs(x-1, y, n, k);
dfs(x+1, y, n, k);
dfs(x, y-1, n, k);
dfs(x, y+1, n, k);
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner input = new Scanner(System.in);
int n = input.nextInt();
input.nextLine(); //记得换行输入
for(int i=0; i<n; i++) { //输入海域像素
String pixel = input.nextLine();//照片保证第1行、第1列、第N行、第N列的像素都是海洋。
map[i] = pixel.toCharArray();
}
int len = 0;
for(int i=0; i<n; i++) { //注意:从这里判断其实就可以找出两个岛屿了,因为两个岛屿之间隔着海洋'.'
for(int j=0; j<n; j++) {//第一个岛屿的陆地已经被访问完,接下来,先访问'.',,此时不进行搜索;再次遇到'#',才会进行dfs搜索,此时len++
if(map[i][j]=='#' && !vis[i][j]) {//如果是陆地‘#’,且没有进行过访问,则进行寻找
dfs(i, j, n, len);
len++; //岛屿数目加1
}
}
}
int sum = 0;
for(int i=0; i<len; i++) {
// System.out.println(ans[i]);
if(ans[i] == 0) { //ans[i]=0说明该岛屿会被淹没,>0说明岛屿存在不可淹没点
sum++;
}
}
System.out.println(sum);
}
}