day50 图论章节刷题Part02(99.岛屿数量 深搜、99.岛屿数量 广搜、100.岛屿的最大面积)
前言:前段时间论文开题落下了很多进度,今天开始会尽快赶上
99.岛屿数量 深搜
思路:对地图进行遍历遇到一个没有遍历过的陆地节点,计数器就+1,并把该节点所能遍历到的陆地都标记上;遇到标记过的陆地节点和海洋节点的时候直接跳过。
代码如下:
import java.util.Scanner;
public class Main{
//定义前进的方向
public static int[][] dir={{0,1},{1,0},{-1,0},{0,-1}};
//深度搜索函数
public static void dfs(boolean[][] visited,int[][] grid,int x,int y){
for(int i=0;i<4;i++){
int nextX=x+dir[i][0];
int nextY=y+dir[i][1];
if(nextX<0 || nextY<0 || nextX>=grid.length || nextY>=grid[0].length) continue;
if(!visited[nextX][nextY] && grid[nextX][nextY]==1){
visited[nextX][nextY]=true;
dfs(visited,grid,nextX,nextY);
}
}
}
public static void main (String[] args) {
//构建地图
Scanner scan = new Scanner(System.in);
int n=scan.nextInt();
int m=scan.nextInt();
int[][] grid=new int[n][m];
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
grid[i][j]=scan.nextInt();
}
}
//判断是否为岛屿
int result=0;
boolean[][] visited=new boolean[n][m];
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
if(!visited[i][j] && grid[i][j]==1){
result++;
visited[i][j]=true;
dfs(visited,grid,i,j);
}
}
}
System.out.println(result);
}
}
99.岛屿数量 广搜
注意:要在节点加入队列时就标记走过,如果从队列拿出来的时候再标记走过就会导致很多节点重复加入队列。
广度搜索使用队列存放下一层搜索的节点,与DFS的区别是不需要调用自身,把队列中的元素遍历完即可。
代码如下:
import java.util.*;
class Pair{
int x;
int y;
public Pair(int x, int y) {
this.x = x;
this.y = y;
}
}
public class Main{
//定义前进的方向
public static int[][] dir={{0,1},{1,0},{-1,0},{0,-1}};
public static void bfs(boolean[][] visited,int[][] grid,int x,int y){
Queue<Pair> queue=new LinkedList<>();
queue.add(new Pair(x,y));
visited[x][y]=true;
while(!queue.isEmpty()){
Pair cur=queue.poll();
int curX=cur.x;
int curY=cur.y;
for(int i=0;i<4;i++){
int nextX=curX+dir[i][0];
int nextY=curY+dir[i][1];
if(nextX<0 || nextY<0 || nextX>=grid.length || nextY>=grid[0].length) continue;
if(!visited[nextX][nextY] && grid[nextX][nextY]==1){
queue.add(new Pair(nextX,nextY));
visited[nextX][nextY]=true;
}
}
}
}
public static void main (String[] args) {
Scanner scan = new Scanner(System.in);
int n=scan.nextInt();
int m=scan.nextInt();
int[][] grid=new int[n][m];
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
grid[i][j]=scan.nextInt();
}
}
int result=0;
boolean[][] visited=new boolean[n][m];
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
if(!visited[i][j] && grid[i][j]==1){
result++;
bfs(visited,grid,i,j);
}
}
}
System.out.println(result);
}
}
100.岛屿的最大面积
思路:只需要在标记一个陆地节点周边所有陆地节点时对这个岛屿的面积计数即可,最后比较获得最大的面积。使用全局静态变量count来计数。
dfs只处理下一个节点,即在主函数遇到岛屿就计数为1,dfs处理接下来的相邻陆地.
代码如下:
import java.util.Scanner;
public class Main{
//定义前进的方向
public static int[][] dir={{0,1},{1,0},{-1,0},{0,-1}};
public static int count;
//深度搜索函数
public static void dfs(boolean[][] visited,int[][] grid,int x,int y){
for(int i=0;i<4;i++){
int nextX=x+dir[i][0];
int nextY=y+dir[i][1];
if(nextX<0 || nextY<0 || nextX>=grid.length || nextY>=grid[0].length) continue;
if(!visited[nextX][nextY] && grid[nextX][nextY]==1){
visited[nextX][nextY]=true;
count++;
dfs(visited,grid,nextX,nextY);
}
}
}
public static void main (String[] args) {
//构建地图
Scanner scan = new Scanner(System.in);
int n=scan.nextInt();
int m=scan.nextInt();
int[][] grid=new int[n][m];
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
grid[i][j]=scan.nextInt();
}
}
//判断是否为岛屿
boolean[][] visited=new boolean[n][m];
int result=0;
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
if(!visited[i][j] && grid[i][j]==1){
count=1;
visited[i][j]=true;
dfs(visited,grid,i,j);
}
if(count>result) result=count;
}
}
System.out.println(result);
}
}