赞
踩
题目:101. 孤岛的总面积 (kamacoder.com)
思路:无
- 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里面需要判断岛屿时候接触边缘
思路:判断周围也没有岛屿,上下左右都没有,那就将当前位置变为0
- 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;
- }
- }
- 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);
- }
- }
先标记所有非孤岛,再沉没所有孤岛,再撤销所有非孤岛标记
思路:我需要找到最大的数字,然后再用dfs搜索?以每一个格子为中心,画一个十字,只要有朝向第一组边界和朝向第二组边界的递减数组即可,写一个函数,计算水流能否到达第一组边界,另一个函数计算水流能否到达第二组边界,两个函数返回均为true时,记录该坐标
- 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;
- }
- }
- 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效率更高
题目:104. 建造最大岛屿 (kamacoder.com)
思路:感觉肯定是要找到最大的岛屿,再去连接,或者是第二大的,又或者是岛屿从大到小,都试一遍,逐个将岛屿的某个边缘变为陆地
这个1 肯定是出现在岛屿的边缘,或许我可以先遍历一遍,找到所有的边缘,
- import java.util.Scanner;
-
- class Main{
- public static int N;
- public static int M;
- public static int[][] grid;
- public static boolean[][] visited;
- public static boolean flag;
- public static void main(String[] args){
- Scanner scan = new Scanner(System.in);
- N = scan.nextInt();
- M = scan.nextInt();
- grid = new int[N][M];
- for(int i=0; i<N; i++){
- for(int j=0; j<M; j++){
- grid[i][j] = scan.nextInt();
- }
- }
-
- // 遍历grid,找到所有的边缘,单元格每与一个陆地接触,就加1
- // 初始值为2,为了区分岛屿的1
- for(int i=0; i<N; i++){
- for(int j=0; j<M; j++){
- grid[i][j] = scan.nextInt();
- }
- }
- }
- public static void dfs(int i, int j){
- if(i<0 || i>=N || j<0 || j>=M){
- return;
- }
- visited[i][j] = true;
- if(grid[i][j]==1) flag = true;
- if(flag){
- if(grid[i][j]==0){
- grid[i][j] =2;
- }else{
- grid[i][j]+=1;
- }
- }
- dfs(i-1,j);
- dfs(i+1,j);
- dfs(i,j-1);
- dfs(i,j+1);
- }
-
- }
- import java.util.Arrays;
- import java.util.Map;
- import java.util.Scanner;
-
- // 逆向思维
- public class Main {
- static int[][] dirs = {{1,0},{-1,0},{0,1},{0,-1}};
- static int ans = 0, area = 1;
- static boolean[][] visited;
- public static void main(String[] args) {
- Scanner sc = new Scanner(System.in);
- int n = sc.nextInt(); // row
- int m = sc.nextInt(); // col
- int[][] graph = new int[n][m];
-
- for (int i = 0; i < n; i++) {
- for (int j = 0; j < m; j++) {
- graph[i][j] = sc.nextInt();
- }
- }
-
-
- boolean flag = false;
-
- // 遍历
- for (int i = 0; i < n; i++) {
- for (int j = 0; j < m; j++) {
- area = 1;
- visited = new boolean[n][m];
- if (graph[i][j] == 0){
- dfs(i, j, graph, n, m);
- flag = true;
-
- }
- }
- }
-
- System.out.println(flag ? ans : n * m);
- }
-
- private static void dfs(int row, int col, int[][] graph, int n, int m) {
- ans = Math.max(ans, area);
- visited[row][col] = true;
- for (int[] dir : dirs) {
- int newX = dir[0] + row;
- int newY = dir[1] + col;
- if(newX >= 0 && newX < n && newY >= 0 && newY < m && graph[newX][newY] == 1 && !visited[newX][newY]){
- area++;
- dfs(newX,newY,graph,n,m);
- }
- }
- }
-
- }
- import java.util.*;
-
- public class Main {
-
- static int n, m;
- static int count;
- static int[][] dir = {{0, 1}, {1, 0}, {-1, 0}, {0, -1}}; // 四个方向
-
- public static void main(String[] args) {
- Scanner scanner = new Scanner(System.in);
- n = scanner.nextInt();
- 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();
- }
- }
-
- boolean[][] visited = new boolean[n][m]; // 标记访问过的点,初始化为false
- Map<Integer, Integer> gridNum = new HashMap<>();
- int mark = 2; // 记录每个岛屿的编号
- boolean isAllGrid = true; // 标记是否整个地图都是陆地
-
- // 计算每个岛屿的面积并标记
- for (int i = 0; i < n; i++) {
- for (int j = 0; j < m; j++) {
- if (grid[i][j] == 0) isAllGrid = false;
- if (!visited[i][j] && grid[i][j] == 1) {
- count = 0;
- dfs(grid, visited, i, j, mark); // 将与其链接的陆地都标记上 true
- gridNum.put(mark, count); // 记录每一个岛屿的面积
- mark++; // 记录下一个岛屿编号
- }
- }
- }
-
- if (isAllGrid) {
- System.out.println(n * m); // 如果都是陆地,返回全面积
- return; // 结束程序
- }
-
- // 以下逻辑是根据添加陆地的位置,计算周边岛屿面积之和
- int result = 0; // 记录最后结果
- Set<Integer> visitedGrid = new HashSet<>(); // 标记访问过的岛屿
-
- for (int i = 0; i < n; i++) {
- for (int j = 0; j < m; j++) {
- count = 1; // 记录连接之后的岛屿数量
- visitedGrid.clear(); // 每次使用时,清空
- if (grid[i][j] == 0) {
- for (int k = 0; k < 4; k++) {
- int neari = i + dir[k][0]; // 计算相邻坐标
- int nearj = j + dir[k][1];
- if (neari < 0 || nearj < 0 || neari >= n || nearj >= m) continue;
- if (visitedGrid.contains(grid[neari][nearj])) continue; // 添加过的岛屿不要重复添加
- // 把相邻四面的岛屿数量加起来
- count += gridNum.get(grid[neari][nearj]);
- visitedGrid.add(grid[neari][nearj]); // 标记该岛屿已经添加过
- }
- }
- result = Math.max(result, count);
- }
- }
-
- System.out.println(result);
- }
-
- // 深度优先搜索函数
- private static void dfs(int[][] grid, boolean[][] visited, int x, int y, int mark) {
- if (visited[x][y] || grid[x][y] == 0) return;
- visited[x][y] = true; // 标记访问过
- grid[x][y] = mark; // 给陆地标记新标签
- count++;
- for (int i = 0; i < 4; i++) {
- int nextx = x + dir[i][0];
- int nexty = y + dir[i][1];
- if(nextx <0 || nextx >=n || nexty<0 || nexty >=m) continue;
- dfs(grid, visited, nextx, nexty, mark);
-
- }
- }
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。