传送门:(方便AC你的代码)
“蓝桥杯”练习系统 (lanqiao.cn)http://lx.lanqiao.cn/problem.page?gpid=T2725
你有一张某海域NxN像素的照片,".“表示海洋、”#"表示陆地,如下所示:
.......
.##....
.##....
....##.
..####.
...###.
.......
####其中"上下左右"四个方向上连在一起的一片陆地组成一座岛屿。例如上图就有2座岛屿。
####由于全球变暖导致了海面上升,科学家预测未来几十年,岛屿边缘一个像素的范围会被海水淹没。具体来说如果一块陆地像素与海洋相邻(上下左右四个相邻像素中有海洋),它就会被淹没。
####例如上图中的海域未来会变成如下样子:
…....
…....
…....
…....
…#…
…....
…....
####请你计算:依照科学家的预测,照片中有多少岛屿会被完全淹没。
【输入格式】
第一行包含一个整数N。 (1 <= N <= 1000)
以下N行N列代表一张海域照片。
照片保证第1行、第1列、第N行、第N列的像素都是海洋。
【输出格式】
一个整数表示答案。
【输入样例】
7
.......
.##....
.##....
....##.
..####.
...###.
.......
【输出样例】
1
这道题很明显搜索题,具体用dfs还是bfs看你自己吧,本蒟蒻是想到了bfs,细节都在代码里:
import java.io.*;
import java.util.*;
class Main {
static int n,pre,now; //n存储海域大小,pre存储淹没前岛屿数量,now为现在岛屿数量
static char[][] mp;
static boolean[][] vis; //vis数组记忆化
static int[] dx={-1,1,0,0}; //纵坐标方向偏移量
static int[] dy={0,0,1,-1}; //横坐标方向偏移量
public static void main(String[] args) throws IOException{
Scanner sc = new Scanner(System.in);
n=sc.nextInt();sc.nextLine();
mp=new char[n][n];vis=new boolean[n][n];
for(int i=0;i<n;i++){
mp[i]=sc.nextLine().toCharArray();
}
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(mp[i][j]=='#'&&!vis[i][j]){//该点是岛屿一部分,并且没有拜访过
bfs(i,j);
pre++; //vis数组保证同一个岛屿,只进行一次pre的自加
}
}
}
System.out.println(pre-now);
}
static void bfs(int x,int y){ //标准广搜
Queue<int[]> q = new LinkedList<>();
q.offer(new int[]{x,y});
boolean add=true; //add用来保证对于同一个岛屿,now只自加一次
vis[x][y]=true;
while(!q.isEmpty()){
int[] p=q.remove();
int px=p[0];
int py=p[1];
boolean flag=false;//flag用来判断是否进行now++步骤
for(int i=0;i<4;i++){
int nx=px+dx[i];
int ny=py+dy[i];
if(0<=nx&&nx<n&&0<=ny&&ny<n&&mp[nx][ny]=='#'&&!vis[nx][ny]){
vis[nx][ny]=true;
q.offer(new int[]{nx,ny});
}
if(mp[nx][ny]!='#') flag=true;//如果px,py点周围不是岛屿,flag为true
}
if(!flag&&add) {
//如果flag为false,即px,py点周围全是岛屿,那么now++
//同时add变为false,保证对于同一个岛屿,now只自加一次
now++;
add=false;
}
}
}
}