Кратчайший путь в сетке с использованием BFS

#python #graph #shortest-path #breadth-first-search

#python #График #кратчайший путь #поиск по ширине

Вопрос:

Сетка состоит из следующих элементов в виде списка списков python

 g = [
    ['1', '1', '1', '1', '1'],
    ['S', '1', 'X', '1', '1'],
    ['1', '1', '1', '1', '1'],
    ['X', '1', '1', 'E', '1'],
    ['1', '1', '1', '1', 'X']
]
  

S указывает на начало, E указывает на конец.

1 указывает разрешенные пути, X — недопустимые пути

Простой код обхода BFS является

 def find_path_bfs(s, e, grid):
    queue = list()
    path = list()
    queue.append(s)

    while len(queue) > 0:
        node = queue.pop(0)
        path.append(node)
        mark_visited(node, v)

        if node == e:
            break

        adj_nodes = get_neighbors(node, grid)
        for item in adj_nodes:
            if is_visited(item, v) is False:
                queue.append(item)

    return path
  

Алгоритм, насколько я могу судить, проходит правильно со следующим выводом

 [(1, 0), (1, 1), (2, 0), (0, 0), (2, 1), (0, 1), (2, 1), (0, 1), (2, 2), (3, 1), (0, 2), (2, 2), (3, 1), (0, 2), (2, 3), (3, 2), (3, 2), (4, 1), (0, 3), (2, 3), (3, 2), (3, 2), (4, 1), (0, 3), (2, 4), (3, 3)]
  

Каждый кортеж в списке представляет индексы для узла в исходном графике.

Как можно переписать мой код BFS, чтобы вернуть кратчайший путь вместо всего пройденного пути для достижения конечного узла?Я потратил часы, чтобы найти ответы самостоятельно, но пока мне это не удалось.

Ответ №1:

Чтобы получить кратчайший путь, вы также должны сохранить путь к текущему узлу в своей очереди, поэтому формат элемента очереди будет:

 (node, path_to_this_node)
  

Измененный код:

 def find_path_bfs(s, e, grid):
    queue = [(s, [])]  # start point, empty path

    while len(queue) > 0:
        node, path = queue.pop(0)
        path.append(node)
        mark_visited(node, v)

        if node == e:
            return path

        adj_nodes = get_neighbors(node, grid)
        for item in adj_nodes:
            if not is_visited(item, v):
                queue.append((item, path[:]))

    return None  # no path found
  

Комментарии:

1. Я все еще пытаюсь понять ваше решение и то, как оно решило проблему, но оно решило проблему элегантно.