题目描述
给定一个由 1(陆地)和 0(水)组成的矩阵,岛屿指的是由水平或垂直方向上相邻的陆地单元格组成的区域,且完全被水域单元格包围。孤岛是那些位于矩阵内部、所有单元格都不接触边缘的岛屿。
现在你需要计算所有孤岛的总面积,岛屿面积的计算方式为组成岛屿的陆地的总数。
输入描述
第一行包含两个整数 N, M,表示矩阵的行数和列数。之后 N 行,每行包含 M 个数字,数字为 1 或者 0。
输出描述
输出一个整数,表示所有孤岛的总面积,如果不存在孤岛,则输出 0。
输入示例
4 5
1 1 0 0 0
1 1 0 0 0
0 0 1 0 0
0 0 0 1 1
输出:0
import java.util.*;
public class Main {
private static int count = 0;// 用于存储岛屿面积的全局变量
// 方向数组:表示四个方向(右、下、上、左)
private static final int[][] dir = {{0, 1}, {1, 0}, {-1, 0}, {0, -1}};
public static void main(String[] args) {
//输入
Scanner scanner=new Scanner(System.in);
int n=scanner.nextInt();
int m=scanner.nextInt();
int[][] grid=new int[n][m];
// 读取地图数据
for(int i=0;i queue=new LinkedList<>();
queue.add(new int[]{x, y}); // 将起点加入队列
grid[x][y] = 0; // 只要加入队列,立刻标记为水,防止重复访问
count++; // 计数+1(当前岛屿的第一个陆地)
//step2:遍历
while (!queue.isEmpty()) {
int[] cur = queue.poll(); // 取出队列头部的坐标
int curX = cur[0], curY = cur[1];
// 遍历四个方向
for (int i = 0; i < 4; i++) {
int nextX = curX + dir[i][0];
int nextY = curY + dir[i][1];
// 越界检查:如果超出边界,则跳过
if (nextX < 0 || nextX >= grid.length || nextY < 0 || nextY >= grid[0].length)
continue;
// 如果是陆地(1),加入队列,并标记为水(0)
if(grid[nextX][nextY]==1){
queue.add(new int[]{nextX,nextY});
count++;//计数+1,表示该陆地属于同一个岛屿
grid[nextX][nextY]=0;//立刻标记,防止重复访问
}
}
}
}
}
题目描述:
给定一个由 1(陆地)和 0(水)组成的矩阵,岛屿指的是由水平或垂直方向上相邻的陆地单元格组成的区域,且完全被水域单元格包围。孤岛是那些位于矩阵内部、所有单元格都不接触边缘的岛屿。
现在你需要将所有孤岛“沉没”,即将孤岛中的所有陆地单元格(1)转变为水域单元格(0)。
输入描述:
第一行包含两个整数 N, M,表示矩阵的行数和列数。
之后 N 行,每行包含 M 个数字,数字为 1 或者 0,表示岛屿的单元格。
输出描述
输出将孤岛“沉没”之后的岛屿矩阵。
输入示例:
4 5
1 1 0 0 0
1 1 0 0 0
0 0 1 0 0
0 0 0 1 1
输出示例:
1 1 0 0 0
1 1 0 0 0
0 0 0 0 0
0 0 0 1 1
import java.util.Scanner;
public class Main{
static int[][] dir={{-1,0},{0,-1},{1,0},{0,1}};
public static void main(String[] args){
//输入
Scanner scanner=new Scanner(System.in);
int n=scanner.nextInt();
int m=scanner.nextInt();
int[][] grid=new int[n][m];
for(int i=0;i=grid.length||nextY<0||nextY>=grid[0].length){
continue;
}
//不符合条件,不继续遍历[水或已经变为2]
if(grid[nextX][nextY]==0||grid[nextX][nextY]==2) continue;
dfs(grid,nextX,nextY);
}
}
}
题目描述:
现有一个 N × M 的矩阵,每个单元格包含一个数值,这个数值代表该位置的相对高度。矩阵的左边界和上边界被认为是第一组边界,而矩阵的右边界和下边界被视为第二组边界。
矩阵模拟了一个地形,当雨水落在上面时,水会根据地形的倾斜向低处流动,但只能从较高或等高的地点流向较低或等高并且相邻(上下左右方向)的地点。我们的目标是确定那些单元格,从这些单元格出发的水可以达到第一组边界和第二组边界。
输入描述:
第一行包含两个整数 N 和 M,分别表示矩阵的行数和列数。
后续 N 行,每行包含 M 个整数,表示矩阵中的每个单元格的高度。
输出描述:
输出共有多行,每行输出两个整数,用一个空格隔开,表示可达第一组边界和第二组边界的单元格的坐标,输出顺序任意。
输入示例:
5 5
1 3 1 2 4
1 2 1 3 2
2 4 7 2 1
4 5 6 1 1
1 4 1 2 1
输出示例:
0 4
1 3
2 2
3 0
3 1
3 2
4 0
4 1
import java.util.*;
public class Main {
// 采用 DFS 进行搜索
public static void dfs(int[][] heights, int x, int y, boolean[][] visited, int preH) {
// 遇到边界或者访问过的点,直接返回
if (x < 0 || x >= heights.length || y < 0 || y >= heights[0].length || visited[x][y]) return;
// 不满足水流入条件的直接返回
if (heights[x][y] < preH) return;
// 满足条件,设置为true,表示可以从边界到达此位置
visited[x][y] = true;
// 向下一层继续搜索
dfs(heights, x + 1, y, visited, heights[x][y]);
dfs(heights, x - 1, y, visited, heights[x][y]);
dfs(heights, x, y + 1, visited, heights[x][y]);
dfs(heights, x, y - 1, visited, heights[x][y]);
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int m = sc.nextInt();
int n = sc.nextInt();
int[][] heights = new int[m][n];
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
heights[i][j] = sc.nextInt();
}
}
// 初始化两个二位boolean数组,代表两个边界
boolean[][] pacific = new boolean[m][n];
boolean[][] atlantic = new boolean[m][n];
// 从左右边界出发进行DFS
for (int i = 0; i < m; i++) {
dfs(heights, i, 0, pacific, Integer.MIN_VALUE);
dfs(heights, i, n - 1, atlantic, Integer.MIN_VALUE);
}
// 从上下边界出发进行DFS
for (int j = 0; j < n; j++) {
dfs(heights, 0, j, pacific, Integer.MIN_VALUE);
dfs(heights, m - 1, j, atlantic, Integer.MIN_VALUE);
}
// 当两个边界二维数组在某个位置都为true时,符合题目要求
List> res = new ArrayList<>();
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (pacific[i][j] && atlantic[i][j]) {
res.add(Arrays.asList(i, j));
}
}
}
// 打印结果
for (List list : res) {
for (int k = 0; k < list.size(); k++) {
if (k == 0) {
System.out.print(list.get(k) + " ");
} else {
System.out.print(list.get(k));
}
}
System.out.println();
}
}
}
题目描述:
给定一个由 1(陆地)和 0(水)组成的矩阵,你最多可以将矩阵中的一格水变为一块陆地,在执行了此操作之后,矩阵中最大的岛屿面积是多少。
岛屿面积的计算方式为组成岛屿的陆地的总数。岛屿是被水包围,并且通过水平方向或垂直方向上相邻的陆地连接而成的。你可以假设矩阵外均被水包围。
输入描述:
第一行包含两个整数 N, M,表示矩阵的行数和列数。之后 N 行,每行包含 M 个数字,数字为 1 或者 0,表示岛屿的单元格。
输出描述:
输出一个整数,表示最大的岛屿面积。
输入示例:
4 5
1 1 0 0 0
1 1 0 0 0
0 0 1 0 0
0 0 0 1 1
输出示例
6
import java.util.*;
public class Main{
//global
static int count;//计数岛屿的面积
static int mark;//标记岛屿
static int[][] dirs={{0,1},{0,-1},{1,0},{0,-1}};//方位
public static void main(String[] args){
//接收输入
Scanner sc=new Scanner(System.in);
int m=sc.nextInt();
int n=sc.nextInt();
int[][] grid=new int[m][n];
for(int i=0;i getSize=new HashMap<>();
//HashSet 判断某一位置水四周是否存在不同标记编号的岛屿
HashSet set=new HashSet<>();
//boolean,dfs之后是否全是岛屿??
boolean isAllIsland=true;
//1.计算每个岛屿面积:遍历二维数组进行dfs,标记每片岛屿的编号,记录对应的面积
for(int i=0;i=m||nextY<0||nextY>=n){continue;}
//当前标记
int curMark=grid[nextX][nextY];
//if[当前相邻的岛屿已经遍历过][HashMap不存在这个编号],继续搜索
if(set.contains(curMark)||!getSize.containsKey(curMark)) continue;
set.add(curMark);
curSize+=getSize.get(curMark);
}
result=Math.max(result,curSize);
}
}
System.out.println(result);
}
public static void dfs(int[][] grid,boolean[][] visited,int x,int y){
//遇到边界,直接return
if(x<0||x>=grid.length||y<0||y>=grid[0].length) return;
//遇到已经访问过的或者遇到海水,直接返回
if(visited[x][y]||grid[x][y]==0) return;
visited[x][y]=true;
count++;
grid[x][y]=mark;
//继续向下层搜索[上下左右]
dfs(grid,visited,x,y+1);
dfs(grid,visited,x,y-1);
dfs(grid,visited,x+1,y);
dfs(grid,visited,x-1,y);
}
}