Я столкнулся с этой довольно интересной проблемой, когда у нас есть лабиринт 4х4 и робот, пытающийся добраться до цели. Дело в том, что вы должны найти последовательность предопределенных команд, которая всегда приведет к тому, что робот достигнет цели.
Допустим, у нас есть такой лабиринт:
x . . .
. # # .
. # # .
. . . g
Этот конкретный лабиринт может быть решен, например, с помощью последовательностей команд DDDRRR
или RRRDDD
, где R = вправо, L = влево, U = вверх и D = вниз (дух).
Однако ни одна из этих последовательностей не решит этот лабиринт:
x . # .
. . . .
# . . .
. . . g
Робот всегда начинается сверху слева, цель всегда внизу справа, а лабиринт всегда представляет собой 2D матрицу 4х4.
Я уже реализовал алгоритм, который дал мне выигрышную последовательность из 78 команд. Я точно знаю, что по крайней мере существует решение для 29 команд (кто-то другой выполнил это).
Этой проблеме на самом деле несколько лет, и поэтому я потерял алгоритм, который использовал в то время, однако основная идея состояла в том, чтобы выполнить поиск по всем сгенерированным мной лабиринтам и всегда выбирать маршрут, который приводит к наиболее решенному лабиринты. Это фактически дало мне последовательность, длина которой была чуть больше 78; Я сократил некоторые команды вручную, которые я заметил, были излишними.
Да, перебор займет года, как обычно.
Если мне не изменяет память, существует менее 4000 возможных лабиринтов (возможный лабиринт, если существует путь между верхним левым и нижним правым сторонами).
ОЙ! Достаточно, чтобы робот просто достиг цели хотя бы один раз во время выполнения команд. То есть он не должен сидеть на цели после последней команды.
Я заразил кого-нибудь интерес? Как мне подойти к этой проблеме для более эффективного ответа? Спасибо за внимание :)
Что-то веселое: Pastebin
Это (очень) наспех собранный кусочек Java. Это должно скомпилировать и запустить :) Программа вроде как воспроизводит ~ 4000 лабиринтов одновременно. Программа принимает входные данные (w, a, s, d) для UP, LEFT, DOWN и RIGHT, а затем моделирует движение, показывая некоторую статистику. То, что вы можете увидеть на экране, если вы попробуете это, это общее количество препятствий в каждом лабиринте в каждой позиции и общее количество текущих позиций каждого лабиринта. Это трудно объяснить :) Спросите меня, если у вас есть вопросы.
Опять же... не обращайте внимания на ужасный код. Это было написано за 20 минут
Прогресс
Я получил эту идею косвенно из ответа этого пользователя и затем смоделировал ее с помощью Mooing Duck в чате. Идея состоит в том, чтобы найти последовательность, которая решает правую сторону лабиринта. То есть решение, которое решает, по крайней мере, половину всех лабиринтов, а при зеркальном отображении и повторном запуске с самого начала решает оставшиеся лабиринты.
Иллюстрация:
сначала найдите последовательность, первой командой которой является RIGHT, которая решает, например, этот лабиринт:
0 1 0 0
0 1 0 0
0 0 0 0
0 1 0 0
одна такая последовательность - RDDRRRD
. Зеркальный аналог этой последовательности такой, что
R -> D
D -> R
L -> U
U -> L
Что означает RDDRRRD
→ DRRDDDR
Теперь, эта зеркальная последовательность решает лабиринт? Нет, это застревает. Поэтому это недопустимая последовательность даже для этого лабиринта. Нам нужно найти такую последовательность, чтобы она решала, по крайней мере, половину всех лабиринтов, а зеркальный аналог решает остальное при повторном запуске с самого начала.
После простого грубого форсирования всех возможных перестановок R, D и L, я получил несколько возможных последовательностей.
Одной из таких последовательностей является RRDRRRDRLDRDR
Теперь следующая проблема состоит в том, что после выполнения этой последовательности оставшиеся лабиринты находятся в случайном хаосе. Нам нужно получить кратчайшую (оптимальную) последовательность, которая вернет все оставшиеся лабиринты в исходное положение (0, 0). Эту часть я сделал просто вручную (на данный момент). Мой ответ на этот вопрос ни в коем случае не является оптимальным, но он возвращает все лабиринты к началу.
Эта последовательность является LDLUULURUUULULL
После этого мы просто запускаем зеркальную последовательность DDRDDDRDURDRD
, и мы решили все лабиринты.
Эта конкретная последовательность во всей ее полноте:
RRDRRRDRLDRDRLDLUULURUUULULLDDRDDDRDURDRD
- 41 ход
Несмотря на то, что это многообещающий и важный этап, он все еще находится в 12 шагах от наилучшего проверенного решения. Любое понимание очень приветствуется! Также спасибо всем, кто мне до сих пор помог :)
Последовательность сокращается
Я пока не смог программно получить лучший ответ, чем последовательность из 58 ходов. Однако, с помощью метода, описанного выше, и просто растирая символы вручную, я смог сжать последовательность до 33 символов. Эта последовательность ниже:
RRDRRDRLDRDLDLULLLDDRDDRDRURRRDDR
- 33 хода
Хотя последовательность теперь очень близка к цели 29, я все еще ищу программное решение такого же калибра. Там нет логики, которую я использовал при удалении символов из последовательности - я просто удалил символ и проверил, если он решает все лабиринты, промыть и повторить.