Программирование теории: Решите лабиринт

Что возможные пути состоят в том, чтобы решить лабиринт?
У меня есть две идеи, но я думаю, что они не очень изящны.

Основная ситуация: у Нас есть матрица, и элементы в этой матрице заказаны способом, что она представляет лабиринт с одним путем в, и один.

Моя первая идея состояла в том, чтобы отправить робот через лабиринт, после одной стороны, пока это не вне лабиринта. Я думаю, что это - очень медленное решение.

Второй передает через каждый последовательный объект, отмеченный с 1, проверки, куда он может пойти (право, вниз, оставленный) выбирают один путь, и он продолжает свой путь там. Это еще медленнее, чем первое.

Конечно, это немного быстрее, если я делаю эти двух ботов многопоточными на каждом перекрестке, но это - также не лучший способ.

Должны быть лучшие решения отправить бота через лабиринт.

Править
Во-первых: Спасибо за хорошие ответы!

Вторая часть моего вопроса: Что сделать в случае, если у нас есть многомерный график? Есть ли специальные методы для этого, или действительно ли ответ Justin L. применим для этого также?
Я думаю, что это не лучший способ для этого случая.

Третий вопрос:
Какой из этих алгоритмов решателя лабиринта является самым быстрым? (Просто гипотетически)

67
задан 7 revs, 6 users 67% 15 September 2014 в 15:51
поделиться

9 ответов

Лабиринт можно представить как дерево.

     A
    / \
   /   \
  B     C
 / \   / \
D   E F   G
   / \     \
  H   I     J
 / \
L   M
   / \
  **  O

(which could possibly represent)

        START
        +   +---+---+
        | A   C   G |
    +---+   +   +   +
    | D   B | F | J |
+---+---+   +---+---+
| L   H   E   I |
+---+   +---+---+
    | M   O |
    +   +---+
    FINISH

(ignoring left-right ordering on the tree)

Где каждый узел является стыком путей. D, I, J, L и O — тупики, а ** — цель. Конечно, в реальном дереве каждый узел может иметь до трех потомков.

Ваша цель теперь просто найти, какие узлы пройти, чтобы найти финиш. Подойдет любой старый алгоритм поиска по дереву.

Глядя на дерево, довольно легко увидеть правильное решение, просто «проследив» от ** в самой глубокой части дерева:

A B E H M **

Обратите внимание, что этот подход становится лишь немного сложнее, когда у вас есть "петли" в вашем лабиринте (т.е. когда это возможно, не возвращаясь, вы повторно входите в проход, через который вы уже прошли). Проверьте комментарии для одного хорошего решения.

Теперь давайте посмотрим на ваше первое решение, которое вы упомянули, применительно к этому дереву.

Ваше первое решение, по сути, Поиск в глубину , что на самом деле не так уж и плохо. На самом деле это довольно хороший рекурсивный поиск. По сути, он говорит: «Всегда сначала выбирайте самый правый подход. Если там ничего нет, вернитесь назад до первого места, где вы можете пойти прямо или влево, а затем повторите.

Поиск в глубину будет искать дерево выше в этом порядке. :

A B D (backtrack) E H L (backtrack) M ** (backtrack) O (backtrack thrice) I
(backtrack thrice) C F (backtrack) G J

Обратите внимание, что вы можете остановиться, как только найдете **.

Однако, когда вы на самом деле программируете поиск в глубину, использование рекурсивного программирования делает все намного проще. методы также работают, и вам никогда не придется явно программировать, как вернуться назад.Ознакомьтесь с соответствующей статьей для реализации.

Другой способ поиска в дереве — это решение Breadth-First , которое ищет в деревьях по Он будет искать в приведенном выше дереве в следующем порядке:

A (next level) B C (next level) D E F G (next level)
H I J (next level) L M (next level) ** O

Обратите внимание, что из-за природы лабиринта алгоритм в ширину имеет гораздо большее среднее количество проверяемых узлов. очередь путей для поиска, и каждая итерация извлекает путь из очереди, «взрывая» его ", получая все пути, в которые он может превратиться после одного шага, и помещая эти новые пути в конец очереди. Нет явных команд «следующего уровня» для кода, и они были просто для помощи в понимании.

На самом деле существует целый обширный список способов поиска по дереву. Я только что упомянул два самых простых и простых способа.

Если ваш лабиринт очень, очень длинный и глубокий, в нем есть петли и сумасшествия, и он сложный, я предлагаю алгоритм A* , который является отраслевым стандартным алгоритмом поиска пути, сочетающим алгоритм поиска в ширину. поиск с эвристикой... что-то вроде "интеллектуального поиска в ширину".

В основном это работает следующим образом:

  1. Поместите один путь в очередь (путь, по которому вы проходите только один шаг прямо в лабиринте). Путь имеет «вес», определяемый его текущей длиной + его расстояние по прямой от конца (которое может быть рассчитано математически).
  2. Вытолкните путь с наименьшим весом из очереди.
  3. "Взорвать" путь на каждый путь, которым он может быть после одного шага. (т.е. если ваш путь Правый Левый Левый Правый, то ваши взорванные пути будут Р Л Л Р Р и Р Л Л Р Л, не считая нелегальных, проходящих сквозь стены)
  4. Если один из этих путей имеет цель, то Победа! В противном случае:
  5. Вычислите веса разнесенных путей и поместите их все обратно в очередь (не включая исходный путь).
  6. Отсортируйте очередь по весу, начиная с самого низкого. Затем повторите с шага № 2

И это A*, который я специально выделил, потому что это более или менее стандартный алгоритм поиска пути для всех приложений поиска пути, включая перемещение от одного края карты к другому, избегая бездорожья или гор и т. д. Он работает так хорошо, потому что использует эвристику кратчайшего возможного расстояния, которая придает ему «интеллект».A* настолько универсален, потому что, учитывая любую проблему, если у вас есть доступная эвристика кратчайшего возможного расстояния (у нас простая — прямая линия), вы можете применить ее.

НО важно отметить, что A* не ваш единственный вариант.

На самом деле, в категории алгоритмов обхода дерева Википедии перечислено только 97! (лучшее по-прежнему будет на этой странице, ссылка на которую была указана ранее)

Извините за длину =P (я склонен к бессвязности)

158
ответ дан 24 November 2019 в 14:27
поделиться

Интересный подход, по крайней мере, я нашел его интересно, использовать клеточные автоматы. Короче говоря, «космическая» ячейка, окруженная 3-мя «пристенными» ячейками, превращается в «пристенную» ячейку. В конце остались только пустые клетки на пути к выходу.

Если вы посмотрите на дерево, которое Джастин вложил в свой ответ, то вы увидите, что листовые узлы имеют 3 стены. Обрезайте дерево, пока не появится тропинка.

12
ответ дан 24 November 2019 в 14:27
поделиться

Существует множество алгоритмов решения лабиринтов:

http://en.wikipedia.org/wiki/Maze_solving_algorithm

http://www.astrolog.org/labyrnth/algrithm .htm # resolve

Для робота алгоритм Тремо выглядит многообещающим.

13
ответ дан 24 November 2019 в 14:27
поделиться

Как насчет построения графика из вашей матрицы и использования поиска в ширину, поиска в глубину или алгоритма Дейкстра?

4
ответ дан 24 November 2019 в 14:27
поделиться

Это один из моих любимых алгоритмов на свете ....

1) Move forward
2) Are you at a wall?
2a) If yes, turn left
3) Are you at the finish?
3a) If no, go to 1
3b) If yes, solved
4
ответ дан 24 November 2019 в 14:27
поделиться

Просто идея. Почему бы не добавить туда ботов в моде Монте-Карло. Назовем первое поколение ботов gen0. Мы удерживаем только ботов из gen0, у которых есть непрерывные дороги, таким образом:
-с самого начала до некоторой точки
или -от какой-то точки до конца

Мы запускаем новое поколение ботов в новых случайных точках, затем мы пытаемся соединить дороги ботов поколения 1 с дорогами поколения 0 и посмотреть, получим ли мы непрерывную дорогу от начала и до конца.

Итак, для genn мы пытаемся подключиться к ботам из gen0, gen1, ..., genn-1.

Конечно, поколение длится ограниченное время.

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


несколько хороших сайтов для идей:
http://citeseerx.ist.psu.edu/
http://arxiv.org/

2
ответ дан 24 November 2019 в 14:27
поделиться

У меня была похожая проблема на одном из моих университетских курсов Comp. Sci. Решение, которое мы придумали, заключалось в том, чтобы следовать по левой стене (правая стена будет работать так же хорошо). Вот некоторый псевдокод

While Not At End
    If Square To Left is open,
        Rotate Left
        Go Forward
    Else
        Rotate Right
    End If
Wend

В принципе, это все. Сложная часть заключается в отслеживании направления, в котором вы находитесь, и определении позиции сетки слева от вас на основе этого направления. Это работало во всех тестовых ситуациях, которые я ставил перед ним. Интересно, что решение профессора было примерно таким:

While Not At End
    If Can Go North
        Go North
    ElseIf Can Go East
        Go East
    ElseIf Can Go South
        Go South
    ElseIf Can Go West 
        Go West
    EndIf
Wend

Что будет хорошо работать для большинства простых лабиринтов, но не сработает в лабиринте, который выглядит следующим образом:

SXXXXXXXXXXXXX
   X         X
   X         X
   X         X
 XXX         X
 X X         X
 X XXXXXXXXXXX     XXXE
 X                 X
 XXXXXXXXXXXXXXXXXXX

С S и E в качестве начала и конца.

Если вы не идете вдоль стены, вам придется вести список мест, где вы уже побывали, чтобы при необходимости вернуться назад, когда вы попадете в тупик, и чтобы не попасть в петлю. Если вы идете вдоль стены, нет необходимости следить за тем, где вы были. Хотя вы не найдете самый оптимальный путь через лабиринт, вы всегда пройдете его.

1
ответ дан 24 November 2019 в 14:27
поделиться

Если робот может отслеживать свое местоположение и знать, был ли он в каком-либо месте раньше, тогда поиск в глубину является очевидным алгоритмом. С помощью состязательного аргумента можно показать, что невозможно добиться лучшей производительности в худшем случае, чем поиск в глубину.

Если у вас есть доступные методы, которые не могут быть реализованы роботами, то поиск в ширину может лучше работать для многих лабиринтов, как и алгоритм Дейкстры для поиска кратчайшего пути на графе.

1
ответ дан 24 November 2019 в 14:27
поделиться

Тот же ответ, что и на все вопросы о переполнении стека;)

Используйте vi!

http://www.texteditors.org/cgi-bin/wiki.pl?Vi-Maze

Поистине увлекательно видеть, как текстовый редактор решает ascii-лабиринт, я уверен, что у ребят из emacs есть эквивалент ..

0
ответ дан 24 November 2019 в 14:27
поделиться
Другие вопросы по тегам:

Похожие вопросы: