Advertisement
Gistrec

Поиск пути в лабиринте (Обход в ширину) (Теория)

Feb 4th, 2018
380
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.43 KB | None | 0 0
  1. // У нас есть лабиринт NxN со стенками и проходами
  2. // Т.е. для каждой клетки нужно хранить два состояния
  3. // Пусть стена будет false, а проход - true
  4. // Тогда хранить лабиринт мы будем в
  5. // vector<vector<bool>> map
  6. //
  7. // Самое простое решение задачи - обход в ширину
  8. // Но он реализуемых только для графов
  9. // Поэтому наша задача - сделать что-то подобное графу
  10. // Но что не будет выглядеть говнокодом
  11. //
  12. // 1) Создаём структуру узла графа.
  13. // struct Node{ short X; short Y }
  14. // Она нужна для того, чтобы легко было добавлять
  15. // вершину в очередь вершин, которые нужно пройти
  16. // и в вектор пройденных вершин
  17. //
  18. // 2) Создаём функцию vector<Node> getAdjacentNode(Node &node)
  19. // для получения списка смежных вершин
  20. //
  21. // 3) Создаём массив из пройденных вершин
  22. // vector<Node> usedNode
  23. //
  24. // 4) Нужно создать матрицу, где для каждой вершины будет указан путь, откуда мы к этой вершине добрались
  25. // Нужно для того, чтобы потом восстановить кратчайший путь
  26. // vector<vector<Node>> path размером NxN
  27.  
  28. #include <iostream>
  29. #include <vector>
  30. #include <queue>
  31.  
  32. // структура узла
  33. struct Node {
  34.     short X;
  35.     short Y;
  36.     Node(short X, short Y) {
  37.         this->X = X;
  38.         this->Y = Y;
  39.     }
  40. }
  41.  
  42. // размер лабиринта
  43. short N;
  44. // карта лабиринта
  45. std::vector<std::vector<bool>> map;
  46.  
  47. // массив из пройденных вершин
  48. std::vector<Node> usedNode;
  49.  
  50. // вершины, которые будем обходить
  51. std::queue<Node> queue;
  52.  
  53. // для каждой вершины будет указан путь, откуда мы к этой вершине добрались
  54. std::vector<std::vector<Node>> path;
  55.  
  56. // Функция для получения смежных вершин
  57. // По сути, она смотрит, что если на смежной клетке есть проход
  58. // то создаём вершину с координатами этого прохода
  59. std::vector<Node> getAdjacentNode(Node &node) {
  60.     std::vetor<Node> result;
  61.     if (map[node.X][node.Y - 1]) result.push_back(Node(node.X, node.Y - 1));
  62.     if (map[node.X][node.Y + 1]) result.push_back(Node(node.X, node.Y + 1));
  63.     if (map[node.X - 1][node.Y]) result.push_back(Node(node.X - 1, node.Y));
  64.     if (map[node.X + 1][node.Y]) result.push_back(Node(node.X + 1, node.Y));
  65.     return result;
  66. }
  67.  
  68. // Поиск вершины в векторе пройденных вершин
  69. // Нужна чтобы искать пройдена ли вершина или нет
  70. bool isUsed(Node &node) {
  71.     for (auto elem = usedNode.begin(); elem != usedNode.end(); ++elem) {
  72.         if (*elem == node) return true;
  73.     }
  74.     return false;
  75. }
  76.  
  77.  
  78.  
  79. // Найти кратчайший путь
  80. // Поиск в ширину
  81. // Работает за O(n+m), где n - число вершин, m - число ребер
  82. //
  83. // Сам алгоритм можно понимать как процесс "поджигания" графа:
  84. // на нулевом шаге поджигаем только вершину start.
  85. // На каждом следующем шаге огонь с каждой уже горящей вершины перекидывается на всех её соседей;
  86. // Т.е. за одну итерацию алгоритма происходит расширение "кольца огня" в ширину на единицу (отсюда и название алгоритма).
  87.  
  88. std::vector<Node> shortest_path(Node start) {
  89.     // Добавляем стартовую вершину в начало
  90.     queue.push(start);  
  91.     usedNode.push_back(start);
  92.    
  93.     while (!queue.empty()) {
  94.         Node node = queue.front();
  95.         queue.pop();
  96.         // Говорим, что мы прошли эту вершину
  97.  
  98.         usedNode.push_back(node);
  99.         // Получаем смежные вершины
  100.         std::vector<Node> adjacent_node = getAdjacentNode(node);
  101.  
  102.         // Для каждой смежной вершины
  103.         for (auto n = adjacent_node.begin(); n != adjacent_node.end(); ++n) {
  104.             // Если вершина не пройдена
  105.             if (!isUsed(*n)) {
  106. // TODO:
  107. // Вот тут по идее должна быть проверка, что
  108. // Если хотя бы одна координата (Х или У равна 0 или N)
  109. // То мы должны восстановить путь, и вернуть его из функции
  110.  
  111.                 // Добавляем вершину в конец очереди
  112.                 queue.push(*n);
  113.                 // Текущая вершина (node) является родителем для смежной вершины. Нужно чтобы восстановить путь
  114.                 path[(*n).X][(*n).Y] = node;
  115.             }
  116.         }
  117.     }
  118. }
  119.  
  120.  
  121. int main() {
  122.    
  123. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement