我好想逃却逃不掉-题目讲解

149 阅读2分钟

1.题目解析

在这个问题中,我们需要在一个 N × M 的竞技场迷宫中找出所有“危险位置”的数量。危险位置是指从该位置出发,无论采取什么移动策略,都无法到达出口('O')。

思路

  • 图的表示:将竞技场视为一个图,节点为每个格子,边为可以移动的方向(上下左右)。

  • 可达性分析:从出口位置开始,使用广度优先搜索(BFS)或深度优先搜索(DFS)来标记所有可以到达的格子。所有未被标记的格子即为“危险位置”。

  • 传送器处理:对于传送器(U、D、L、R),在搜索时需要考虑它们的强制传送效果。

  • 边界条件:如果传送器将人传送到竞技场外,则视为死亡。

图解

假设有一个 5 × 5 的竞技场如下:

. . . . O
. U . D .
. . . . .
. L . R .
. . . . .
  • '.' 表示普通地板,可以自由移动。

  • 'O' 是出口。

  • 'U'、'D'、'L'、'R' 是传送器,分别向上、下、左、右传送。

从出口 'O' 开始,进行 BFS 或 DFS,标记所有可以到达的格子。

代码详解

代码

1. 初始化可达性数组和队列

boolean[][] canReach = new boolean[N][M];
Queue<int[]> queue = new LinkedList<>();
  •  canReach 数组用于记录每个位置是否可达,初始时所有位置均为 false。
  • queue 用于存储待处理的位置,采用队列的方式实现 BFS。

2. 初始化出口位置

for (int i = 0; i < N; i++) {
    for (int j = 0; j < M; j++) {
        if (data[i][j] == 'O') {
            canReach[i][j] = true;
            queue.offer(new int[]{i, j});
        }
    }
}
  • 遍历 data 数组,找到所有出口位置(字符为 'O' 的位置),并将其标记为可达,同时将其加入队列

3. 反向传播可达性

while (!queue.isEmpty()) {
    int[] pos = queue.poll();
    int x = pos[0], y = pos[1];

    // 检查上方、下方、左方、右方的格子
    ...
}
  • 使用 BFS 算法,从已知的可达位置开始,检查其四个方向(上、下、左、右)的邻居。
  • 如果邻居位置是可通行的(字符为 'D'、'U'、'L'、'R' 或 '.'),则将其标记为可达,并加入队列。

4. 统计危险位置

int dangerCount = 0;
for (int i = 0; i < N; i++) {
    for (int j = 0; j < M; j++) {
        if (!canReach[i][j]) {
            dangerCount++;
        }
    }
}
  •  遍历 canReach 数组,统计所有不可达的位置数量,存储在 dangerCount 中。

5. 返回结果

return dangerCount;
  • 返回不可达位置的数量。

个人思考与分析

  • 复杂度:该算法的时间复杂度为 O(N M),因为每个格子最多被访问一次。

  • 边界条件:需要特别注意传送器的边界条件,确保不会越界。

  • 扩展性:可以考虑增加更多的元素类型或不同的传送规则,增强算法的适应性。

通过这种方式,我们能够有效地找出竞技场中的所有危险位置,为后续的策略制定提供依据。