玖雨y的算法刷题记录day03——图论

玖雨y的算法刷题记录day03——图论

  • 题目链接:沉没孤岛
  • 题目思路:与day02的孤岛总面积一题思路类似,只不过不能将非孤岛的1直接置为0,这样后续我们也不知道非孤岛都在哪了,要实现其实也很简单,只需要采用一个特殊标记(以下代码标记为2),我们先通过深度优先搜索标记所有非孤岛位置为2,再遍历矩阵将1置为0(孤岛沉没),将2置为1(标记复原)。
import java.util.Scanner;

public class Main {
    
    static int[][] graph;

    static int[][] direction = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};


    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int m = sc.nextInt();
        graph = new int[n][m];

        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                graph[i][j] = sc.nextInt();
            }
        }

        for (int i = 0; i < n; i++) {
            if (graph[i][0] == 1) dfs(i, 0);
            if (graph[i][m - 1] == 1) dfs(i, m - 1);
        }
        for (int j = 0; j < m; j++) {
            if (graph[0][j] == 1) dfs(0, j);
            if (graph[n - 1][j] == 1) dfs(n - 1, j);
        }

        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                if (graph[i][j] == 1) graph[i][j] = 0;
                if (graph[i][j] == 2) graph[i][j] = 1;
            }
        }
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                System.out.print(graph[i][j] + " ");
            }
        }
    }

    private static void dfs(int i, int j) {
        graph[i][j] = 2;
        for (int[] dir : direction) {
            int x = i + dir[0];
            int y = j + dir[1];
            if (x < 0 || x >= graph.length || y < 0 || y >= graph[0].length) continue;
            if (graph[x][y] == 1) {
                dfs(x, y);
            }
        }
    }
}
  • 题目链接:水流问题
  • 题目思路:这道题的思路就相对有些复杂了,一方面,每个位置需要记录两个状态(第一组边界是否可达,第二组边界是否可达),另一方面,在设置递归出口时需要像以往一样采用visited数组记录当前位置是否访问过(注意第一组边界和第二组边界的访问情况也要分开)。至于深度优先遍历的逻辑,我们从边界出发,判断下一个位置的高度是否高于或等于当前位置,如果是则修改reached数组对应下标为true,最终输出结果时,输出reached[·][·][1]和reached[·][·][2]均为true的位置。
import java.util.Scanner;

public class Main {

    static int[][] direction = {{-1, 0}, {0, -1}, {1, 0}, {0, 1}};

    static int[][] graph;
	
	// 记录访问情况
    static boolean[][][] visited;

	// 记录可达情况
    static boolean[][][] reached;

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int m = sc.nextInt();
        graph = new int[n][m];
        // 前两维与graph对应,第三维固定为3,第一组边界修改数组下标为1的位置,第二组边界修改数组下标为2的位置
        visited = new boolean[n][m][3];
        reached = new boolean[n][m][3];
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                graph[i][j] = sc.nextInt();
            }
        }
        for (int i = 0; i < n; i++) {
            dfs(i, 0, 1);
        }
        for (int j = 0; j < m; j++) {
            dfs(0, j, 1);
        }
        for (int i = 0; i < n; i++) {
            dfs(i, m - 1, 2);
        }
        for (int j = 0; j < m; j++) {
            dfs(n - 1, j, 2);
        }
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                if (reached[i][j][1] && reached[i][j][2]) {
                    System.out.println(i + " " + j);
                }
            }
        }

    }

    private static void dfs(int i, int j, int mark) {
        reached[i][j][mark] = true;
        visited[i][j][mark] = true;
        for (int[] dir : direction) {
            int x = i + dir[0];
            int y = j + dir[1];
            if (x < 0 || y < 0 || x >= graph.length || y >= graph[0].length) continue;
            if (graph[i][j] <= graph[x][y] && !visited[x][y][mark]) {
                dfs(x, y, mark);
            }
        }
    }
}
  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值