解题思路
这道题涉及一个迷宫的动态流转问题,需要判断哪些位置无法到达出口。这类问题可以建模为图问题,用图搜索(如DFS/BFS)解决,同时结合传送带的逻辑处理。
核心思路:
-
图建模:
- 将迷宫看作一个二维网格,每个格子是图的一个节点。
- 根据传送带规则,建立节点之间的有向边,形成一个有向图。
- 如果某个点可以进入环(例如,多个传送带形成的循环),或者走出迷宫时会“撞墙”,这个点就是我们需要计数的位置。
-
环检测与状态分类:
-
我们需要判断每个点是否能到达出口,使用三种状态:
0:未访问1:正在访问(检测是否形成环)2:可以到达出口
-
环检测可以通过DFS实现:如果在访问的过程中遇到已经标记为
1的点,说明存在环。
-
-
出口连通性:
- 从出口开始进行反向搜索,标记所有能到达出口的点。
- 反向搜索可以用DFS/BFS完成。
-
统计无法到达出口的位置:
- 对所有点进行遍历,如果点状态未标记为
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);
}
}
代码解析
-
图搜索和连通性检测:
- 每个点的状态在
state二维数组中维护,DFS通过标记和递归实现环检测和连通性检查。
- 每个点的状态在
-
反向连通性:
- 起点是出口,传送带按其方向继续递归。
- 当遇到边界或墙壁时,返回
false,表示无法连通出口。
-
复杂度分析:
- 时间复杂度:每个点最多被访问一次,复杂度为
O(n * m)。 - 空间复杂度:额外使用了
state数组和递归栈,复杂度为O(n * m)。
- 时间复杂度:每个点最多被访问一次,复杂度为
测试用例分析
-
普通传送带交叉: 输入:
mathematica 复制代码 5 5 ..... .RRD. .U.DR .ULL. ....O输出:
10 -
没有传送带: 输入:
python 复制代码 3 3 ... ... ..O输出:
0 -
全环传送带: 输入:
复制代码 3 3 RRR LUL OLL输出:
8
总结
本题考察了复杂路径搜索与环检测问题,重点在于如何结合状态标记和递归逻辑,解决有向图的连通性问题。通过图的建模和DFS实现,能够高效解决问题,并适应大规模输入的场景。