You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

网格最优避障路径最小距离求解及DP+BFS超时优化

问题描述

给定网格(.表示可移动位置,*表示障碍物,S和E分别表示起点和终点),需找到从起点到终点的最优路径(最大化与所有障碍物的距离)中,路径上任意点到障碍物的最小曼哈顿距离。若起点到终点无路径则返回0;若存在路径,例如路径上到障碍物的最近距离为2,则返回2。

我尝试先通过DP计算网格中每个点到最近障碍物的距离,再使用优先队列执行BFS,但仍遇到超时问题,请问还有哪些优化方法?

示例输入

5
..*
.S.
..*
...
..E

答案:2
最优路径为(1,1) -> (1,0) -> (2,0) -> (3,0) -> (4,0) -> (4,1) -> (4,2),路径上到障碍物的最近距离为2。

我的实现代码

from collections import deque
from queue import PriorityQueue
import math  # 补充原代码遗漏的导入
  
def findMaximumDistance(grid):
    matrix = []
    new_matrix = []
    for row in grid: 
        matrix.append(list(row))
        row = [1 if ele != '*' else 0 for ele in row]
        new_matrix.append(list(row))

    # 标记起点和终点
    m, n = len(matrix), len(matrix[0])
    start = None
    end = None
    for i in range(m):
        for j in range(n):
            if matrix[i][j] == 'S':
                start = (i,j)
            elif matrix[i][j]== 'E':
                end = (i,j)

    def updateMatrix(mat):
        m, n = len(mat), len(mat[0])

        for r in range(m):
            for c in range(n):
                if mat[r][c] > 0:
                    top = mat[r - 1][c] if r > 0 else math.inf
                    left = mat[r][c - 1] if c > 0 else math.inf
                    mat[r][c] = min(top, left) + 1

        for r in range(m - 1, -1, -1):
            for c in range(n - 1, -1, -1):
                if mat[r][c] > 0:
                    bottom = mat[r + 1][c] if r < m - 1 else math.inf
                    right = mat[r][c + 1] if c < n - 1 else math.inf
                    mat[r][c] = min(mat[r][c], bottom + 1, right + 1)

        return mat

    new_matrix = updateMatrix(new_matrix)

    def best_first_search():
        nonlocal min_dist
        visited = []
        DIR = [0, 1, 0, -1, 0]
        pq = PriorityQueue()
        pq.put((-new_matrix[start[0]][start[1]], start))
        
        while pq:
            dist, pos = pq.get()
            dist = -dist
            r, c = pos
            min_dist = min(min_dist, dist)
            visited.append((r,c))
            if pos == end:
                break
            for i in range(4):
                nr, nc = r + DIR[i], c + DIR[i + 1]
                if nr < 0 or nr == m or nc < 0 or nc == n or (nr,nc) in visited: continue
                pq.put((-new_matrix[nr][nc],(nr, nc)))
    
    min_dist = float('inf')    
    best_first_search()
    return min_dist if min_dist != float('inf') else 0

优化方案

1. 替换DP为多源BFS计算距离

你当前用DP计算的是网格最短路径步数(切比雪夫距离),如果题目要求曼哈顿距离,需要调整计算逻辑;如果是网格最短路径距离,多源BFS更高效且准确,时间复杂度同为O(mn),但避免DP的两次遍历误差:

def updateMatrix(mat):
    m, n = len(mat), len(mat[0])
    q = deque()
    dist = [[-1]*n for _ in range(m)]
    # 初始化所有障碍物的距离为0并加入队列
    for i in range(m):
        for j in range(n):
            if mat[i][j] == 0:
                dist[i][j] = 0
                q.append((i,j))
    # 多源BFS扩散计算最短距离
    dirs = [(-1,0),(1,0),(0,-1),(0,1)]
    while q:
        x, y = q.popleft()
        for dx, dy in dirs:
            nx, ny = x+dx, y+dy
            if 0<=nx<m and 0<=ny<n and dist[nx][ny] == -1:
                dist[nx][ny] = dist[x][y] + 1
                q.append((nx, ny))
    return dist

2. 替换PriorityQueue为heapq

queue.PriorityQueue是线程安全实现,自带锁机制导致速度较慢,换成heapq模块实现优先队列,能显著提升执行效率:

import heapq

# 在BFS中替换队列实现
pq = []
heapq.heappush(pq, (-new_matrix[start[0]][start[1]], start[0], start[1]))

3. 优化visited结构

原代码用列表存储已访问节点,(nr,nc) in visited是O(k)时间复杂度,换成二维布尔数组后判断时间降为O(1),这是核心性能优化点:

# 初始化二维visited数组
visited = [[False]*n for _ in range(m)]
visited[start[0]][start[1]] = True

# 遍历邻接节点时的判断
if 0 <= nr < m and 0 <= nc < n and not visited[nr][nc]:
    visited[nr][nc] = True
    heapq.heappush(pq, (-new_matrix[nr][nc], nr, nc))

4. 记录节点最优状态,避免重复处理

当前代码的全局min_dist更新逻辑存在缺陷,需为每个节点记录能达到的最大路径最小距离,如果新路径的该值不大于已记录值,直接跳过该节点,减少无效队列操作:

def best_first_search():
    dirs = [(-1,0),(1,0),(0,-1),(0,1)]
    # 记录每个节点的最优路径最小距离
    max_min_dist = [[-1]*n for _ in range(m)]
    max_min_dist[start[0]][start[1]] = new_matrix[start[0]][start[1]]
    pq = []
    heapq.heappush(pq, (-max_min_dist[start[0]][start[1]], start[0], start[1]))

    while pq:
        neg_dist, r, c = heapq.heappop(pq)
        current_min = -neg_dist
        # 若当前路径不是最优,直接跳过
        if current_min < max_min_dist[r][c]:
            continue
        # 到达终点直接返回结果
        if (r,c) == end:
            return current_min
        for dx, dy in dirs:
            nr, nc = r+dx, c+dy
            if 0<=nr<m and 0<=nc<n:
                new_min = min(current_min, new_matrix[nr][nc])
                # 仅当新路径更优时才更新并加入队列
                if new_min > max_min_dist[nr][nc]:
                    max_min_dist[nr][nc] = new_min
                    heapq.heappush(pq, (-new_min, nr, nc))
    return 0

5. 提前终止与边界处理

  • 若起点或终点被障碍物包围(无法抵达),直接返回0;
  • BFS过程中一旦弹出终点节点,立即返回当前结果,无需处理队列剩余元素。

内容的提问来源于stack exchange,提问作者ViridTomb

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 13:20:28