广度优先搜索优化

时间:2018-10-17 19:05:28

标签: python performance optimization graph-theory breadth-first-search

我最近一直在研究图论,并且遇到了以下问题陈述:

给出一个 2D矩阵作为输入,表示一个迷宫(其中“ E ”是矩阵的开始,而“ S ”是最后)),找到从E到S的最短路径的长度。迷宫中的墙壁以“ ”表示,而可到达的空间则以“。”表示。矩阵的外边缘被墙壁覆盖也是一种假设。如果没有从E到S的路径,请return -1

由于未对图形进行加权,因此我尝试使用双端队列来实现 BFS算法。但是,当迷宫开始击中 500x500 时,执行时间将达到10s,而当我尝试提高到 1000x1000 时,情况显然会更糟。

这是我的代码:

from collections import deque

def shortest_path_1(maze):
    wall, clear, endchar, startchar = '#', '.', 'S', 'E'
    height = len(maze)
    width = len(maze[0])

    def find_start(grid):
        for y in range(1, height-1):
            for x in range(1, width-1):
                if grid[y][x] == startchar:
                    return tuple([x, y])

    start = find_start(maze)

    queue = deque([[start]])

    seen = {start}
    while queue:
        path = queue.popleft()
        x, y = path[-1]
        if maze[y][x] == endchar:
            return len(path)-1
        for (x2, y2) in ((x + 1, y), (x - 1, y), (x, y + 1), (x, y - 1)):
            if 0 < x2 < width-1 and 0 < y2 < height-1 and maze[y2][x2] != wall and (x2, y2) not in seen:
                queue.append(path + [(x2, y2)])
                seen.add((x2, y2))

    return -1

到目前为止,我在网站上发现了一些非常有用的答案,但是当前的答案似乎都没有提供我尚未实现的任何其他优化...

谢谢!

编辑:感谢可爱的人编辑了我的问题,使关键字流行:)。这是可以在其上运行算法的矩阵示例:

#####
#E#S#
#.#.#
#...#
#####

这应该返回值 6

EDIT2:修复了一些小错误。

1 个答案:

答案 0 :(得分:0)

如注释中所建议,您不必存储路径。试试这个:

from collections import deque

def shortest_path_1(maze):
    wall, clear, endchar, startchar = '#', '.', 'S', 'E'
    height = len(maze)
    width = len(maze[0])

    def find_start(grid):
        for y in range(1, height-1):
            for x in range(1, width-1):
                if grid[y][x] == startchar:
                    return (x, y, 0)

    start = find_start(maze)

    queue = deque([start])

    seen = set()
    while queue:
        x, y, d = queue.popleft()

        if not 0 <= x < width:
            continue
        if not 0 <= y < height:
            continue
        if maze[y][x] == wall:
            continue

        if maze[y][x] == endchar:
            return d

        if (x, y) in seen:
            continue
        seen.add((x, y))

        queue.append((x+1, y, d+1))
        queue.append((x-1, y, d+1))
        queue.append((x, y+1, d+1))
        queue.append((x, y-1, d+1))

    return -1

maze = [x for x in """
#####
#E#S#
#.#.#
#...#
#####
""".split('\n') if x]

print shortest_path_1(maze)