迷宫的动态流转问题 | 豆包MarsCode AI刷题

100 阅读3分钟

解题思路

这道题涉及一个迷宫的动态流转问题,需要判断哪些位置无法到达出口。这类问题可以建模为图问题,用图搜索(如DFS/BFS)解决,同时结合传送带的逻辑处理。

核心思路:

  1. 图建模

    • 将迷宫看作一个二维网格,每个格子是图的一个节点。
    • 根据传送带规则,建立节点之间的有向边,形成一个有向图。
    • 如果某个点可以进入环(例如,多个传送带形成的循环),或者走出迷宫时会“撞墙”,这个点就是我们需要计数的位置。
  2. 环检测与状态分类

    • 我们需要判断每个点是否能到达出口,使用三种状态:

      • 0:未访问
      • 1:正在访问(检测是否形成环)
      • 2:可以到达出口
    • 环检测可以通过DFS实现:如果在访问的过程中遇到已经标记为1的点,说明存在环。

  3. 出口连通性

    • 从出口开始进行反向搜索,标记所有能到达出口的点。
    • 反向搜索可以用DFS/BFS完成。
  4. 统计无法到达出口的位置

    • 对所有点进行遍历,如果点状态未标记为2,则计数。

实现代码

java
复制代码
import java.util.*;

public class Main {
    public static int solution(int N, int M, char[][] data) {
        int[][] directions = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
        char[] dirMap = {'U', 'D', 'L', 'R'};
        int[][] state = new int[N][M]; // 0: unvisited, 1: visiting, 2: can reach exit
        int[] exit = new int[2];
        
        // Find the exit position
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < M; j++) {
                if (data[i][j] == 'O') {
                    exit[0] = i;
                    exit[1] = j;
                }
            }
        }

        // DFS function to check reachability
        boolean dfs(int x, int y) {
            if (x < 0 || x >= N || y < 0 || y >= M) return false; // Out of bounds
            if (state[x][y] == 2) return true; // Already confirmed to reach exit
            if (state[x][y] == 1) return false; // Found a cycle

            state[x][y] = 1; // Mark as visiting

            int nx = x, ny = y;
            if (data[x][y] == '.') {
                // No forced movement
            } else {
                // Follow the direction of the conveyor
                for (int d = 0; d < 4; d++) {
                    if (data[x][y] == dirMap[d]) {
                        nx = x + directions[d][0];
                        ny = y + directions[d][1];
                        break;
                    }
                }
            }

            // Move to the next position
            if (nx == x && ny == y) {
                // Stay in place (empty cell)
                state[x][y] = 2;
                return true;
            }

            if (nx < 0 || nx >= N || ny < 0 || ny >= M || data[nx][ny] == '.') {
                state[x][y] = 2;
                return true;
            }

            // Recursive DFS for the next cell
            boolean canReach = dfs(nx, ny);
            if (canReach) {
                state[x][y] = 2;
            }
            return canReach;
        }

        // Run DFS from every position
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < M; j++) {
                if (state[i][j] == 0) {
                    dfs(i, j);
                }
            }
        }

        // Count unreachable positions
        int unreachable = 0;
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < M; j++) {
                if (state[i][j] != 2) {
                    unreachable++;
                }
            }
        }
        return unreachable;
    }

    public static void main(String[] args) {
        char[][] pattern = {
            {'.', '.', '.', '.', '.'},
            {'.', 'R', 'R', 'D', '.'},
            {'.', 'U', '.', 'D', 'R'},
            {'.', 'U', 'L', 'L', '.'},
            {'.', '.', '.', '.', 'O'}
        };
        System.out.println(solution(5, 5, pattern) == 10);
    }
}

代码解析

  1. 图搜索和连通性检测

    • 每个点的状态在state二维数组中维护,DFS通过标记和递归实现环检测和连通性检查。
  2. 反向连通性

    • 起点是出口,传送带按其方向继续递归。
    • 当遇到边界或墙壁时,返回false,表示无法连通出口。
  3. 复杂度分析

    • 时间复杂度:每个点最多被访问一次,复杂度为O(n * m)
    • 空间复杂度:额外使用了state数组和递归栈,复杂度为O(n * m)

测试用例分析

  1. 普通传送带交叉: 输入:

    mathematica
    复制代码
    5 5
    .....
    .RRD.
    .U.DR
    .ULL.
    ....O
    

    输出:10

  2. 没有传送带: 输入:

    python
    复制代码
    3 3
    ...
    ...
    ..O
    

    输出:0

  3. 全环传送带: 输入:

    复制代码
    3 3
    RRR
    LUL
    OLL
    

    输出:8


总结

本题考察了复杂路径搜索与环检测问题,重点在于如何结合状态标记和递归逻辑,解决有向图的连通性问题。通过图的建模和DFS实现,能够高效解决问题,并适应大规模输入的场景。