101.孤岛的总面积
题目:101. 孤岛的总面积 (kamacoder.com)
思路:无
答案
java
import java.util.Scanner;
class Main {
private static int N, M;
private static int[][] grid;
private static boolean[][] visited;
private static boolean touchesEdge;
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
N = scanner.nextInt();
M = scanner.nextInt();
grid = new int[N][M];
visited = new boolean[N][M];
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
grid[i][j] = scanner.nextInt();
}
}
int totalIslandArea = 0;
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
if (grid[i][j] == 1 && !visited[i][j]) {
touchesEdge = false;
int islandArea = dfs(i, j);
if (!touchesEdge) {
totalIslandArea += islandArea;
}
}
}
}
System.out.println(totalIslandArea);
}
private static int dfs(int x, int y) {
if (x < 0 || x >= N || y < 0 || y >= M) {
return 0;
}
if (grid[x][y] == 0 || visited[x][y]) {
return 0;
}
if (x == 0 || x == N - 1 || y == 0 || y == M - 1) {
touchesEdge = true;
}
visited[x][y] = true;
int area = 1;
area += dfs(x + 1, y);
area += dfs(x - 1, y);
area += dfs(x, y + 1);
area += dfs(x, y - 1);
return area;
}
}
小结
在dfs里面需要判断岛屿时候接触边缘
102.沉没孤岛
思路:判断周围也没有岛屿,上下左右都没有,那就将当前位置变为0
尝试(标题4)
java
import java.util.Scanner;
class Main{
public static int m;
public static int n;
public static int[][] grid;
public static boolean[][] visited;
public static void main(String[] args){
Scanner scanner = new Scanner(System.in);
n = scanner.nextInt();
m = scanner.nextInt();
grid = new int[n][m];
visited = new boolean[n][m];
for(int i=0; i<n; i++){
for(int j=0; j<m; j++){
grid[i][j] = scanner.nextInt();
}
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (grid[i][j] == 1 && !visited[i][j]) {
int area = dfs(i, j);
if(area == 1) grid[i][j] = 0;
}
}
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
System.out.print(grid[i][j]+" ");
}
System.out.println();
}
}
private static int dfs(int i, int j) {
if (i < 0 || i >= n || j < 0 || j >= m || grid[i][j] == 0 || visited[i][j]) {
return 0;
}
visited[i][j] = true;
int area = 1; // 当前格子的面积为1
// 上
area += dfs(i - 1, j);
// 下
area += dfs(i + 1, j);
// 左
area += dfs(i, j - 1);
// 右
area += dfs(i, j + 1);
return area;
}
}
答案
java
import java.util.Scanner;
class Main {
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 < N; i++) {
for (int j = 0; j < M; j++) {
grid[i][j] = scanner.nextInt();
}
}
// 从边缘开始标记所有与边缘相连的陆地
for (int i = 0; i < N; i++) {
if (grid[i][0] == 1) {
dfs(grid, i, 0, N, M);
}
if (grid[i][M - 1] == 1) {
dfs(grid, i, M - 1, N, M);
}
}
for (int j = 0; j < M; j++) {
if (grid[0][j] == 1) {
dfs(grid, 0, j, N, M);
}
if (grid[N - 1][j] == 1) {
dfs(grid, N - 1, j, N, M);
}
}
// 将所有未标记的陆地(孤岛)沉没
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
if (grid[i][j] == 1) {
grid[i][j] = 0;
} else if (grid[i][j] == 2) {
grid[i][j] = 1;
}
}
}
// 输出结果矩阵
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
System.out.print(grid[i][j] + " ");
}
System.out.println();
}
scanner.close();
}
// 深度优先搜索(DFS)函数
private static void dfs(int[][] grid, int x, int y, int N, int M) {
if (x < 0 || x >= N || y < 0 || y >= M || grid[x][y] != 1) {
return;
}
grid[x][y] = 2; // 标记为非孤岛
dfs(grid, x + 1, y, N, M);
dfs(grid, x - 1, y, N, M);
dfs(grid, x, y + 1, N, M);
dfs(grid, x, y - 1, N, M);
}
}
小结
先标记所有非孤岛,再沉没所有孤岛,再撤销所有非孤岛标记
103.水流问题
思路:我需要找到最大的数字,然后再用dfs搜索?以每一个格子为中心,画一个十字,只要有朝向第一组边界和朝向第二组边界的递减数组即可,写一个函数,计算水流能否到达第一组边界,另一个函数计算水流能否到达第二组边界,两个函数返回均为true时,记录该坐标
尝试(超时)
java
import java.util.Scanner;
import java.util.ArrayList;
class Main{
public static int N;
public static int M;
public static int[][] grid;
public static void main(String[] args){
Scanner scanner = new Scanner(System.in);
N = scanner.nextInt();
M = scanner.nextInt();
grid = new int[N][M];
ArrayList<int[]> dynamicArray = new ArrayList<>();
for(int i=0; i<N; i++){
for(int j=0; j<M; j++){
grid[i][j] = scanner.nextInt();
}
}
for(int i=0; i<N; i++){
for(int j=0; j<M; j++){
if(firstBoundary(i,j) && secondBoundary(i,j)){
dynamicArray.add(new int[]{i,j});
}
}
}
// 输出动态数组中的内容
for (int[] array : dynamicArray) {
System.out.println(array[0] + " " + array[1]);
}
}
public static boolean firstBoundary(int i,int j){
boolean up = true;
boolean left = true;
for(int k=i; k>0; k--){
if(grid[k][j]>grid[i][j]) up = false;
}
for(int k=j; k>0; k--){
if(grid[i][k]>grid[i][j]) left = false;
}
return up|| left;
}
public static boolean secondBoundary(int i,int j){
boolean down = true;
boolean right = true;
for(int k=i; k<N; k++){
if(grid[k][j]>grid[i][j]) down = false;
}
for(int k=j; k<M; k++){
if(grid[i][k]>grid[i][j]) right = false;
}
return down||right;
}
}
答案
java
import java.util.ArrayList;
import java.util.Scanner;
class Main {
public static int N;
public static int M;
public static int[][] grid;
public static boolean[][] canReachFirstBoundary;
public static boolean[][] canReachSecondBoundary;
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
N = scanner.nextInt();
M = scanner.nextInt();
grid = new int[N][M];
canReachFirstBoundary = new boolean[N][M];
canReachSecondBoundary = new boolean[N][M];
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
grid[i][j] = scanner.nextInt();
}
}
// 从第一组边界开始反向DFS
for (int i = 0; i < N; i++) {
dfs(i, 0, canReachFirstBoundary);
dfs(i, M - 1, canReachSecondBoundary);
}
for (int j = 0; j < M; j++) {
dfs(0, j, canReachFirstBoundary);
dfs(N - 1, j, canReachSecondBoundary);
}
// 找出既能到达第一组边界又能到达第二组边界的单元格
ArrayList<int[]> result = new ArrayList<>();
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
if (canReachFirstBoundary[i][j] && canReachSecondBoundary[i][j]) {
result.add(new int[]{i, j});
}
}
}
// 输出结果
for (int[] cell : result) {
System.out.println(cell[0] + " " + cell[1]);
}
}
// 深度优先搜索(DFS)函数
private static void dfs(int x, int y, boolean[][] canReach) {
if (canReach[x][y]) {
return;
}
canReach[x][y] = true;
int[][] directions = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
for (int[] direction : directions) {
int newX = x + direction[0];
int newY = y + direction[1];
if (newX >= 0 && newX < N && newY >= 0 && newY < M && grid[newX][newY] >= grid[x][y]) {
dfs(newX, newY, canReach);
}
}
}
}
小结
反向dfs效率更高