Алгоритм поиска пути с указанным расстоянием / количеством узлов

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

Для расширения у меня есть сетка из плиток. Перемещение может быть только на соседнюю плитку вверх, вниз, влево или вправо (то есть без движения по диагонали). Существует множество правил, определяющих, какую плитку можно и нельзя использовать в пути, но в основном это можно свести к простому логическому выражению, чтобы определить, можно или нельзя использовать плитку (и это можно вычислить еще до запуска алгоритма. . Что меня беспокоит, так это то, что у меня есть заданное расстояние, которое должен иметь путь, то есть каждое движение от одной плитки к соседней - это расстояние, равное единице, а весь путь должен иметь расстояние, равное единице. указанное расстояние, не больше и не меньше. Кроме того, после того, как на плитку наступили (но все плитки доступны в начале алгоритма), на нее нельзя наступить снова, как будто вы играете в старую игру Змейка, где вы надо следить, чтобы не съесть себя.

Я посмотрел на Dijkstra / A * и искал в Google алгоритмы поиска пути, но, насколько я могу судить, все они ориентированы на кратчайший путь, что не приносит мне особой пользы. Меня не волнует, какой это путь, если он следует вышеупомянутым правилам.

Я что-то пропустил, существует ли такой алгоритм и уже существует, или есть простой способ изменить Dijkstra / A *, чтобы получить такой результат? Поскольку я не являюсь носителем английского языка, я могу использовать неправильную терминологию, поэтому приветствую предложения ключевых слов для этого типа алгоритма.


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

Допустим, расстояние должно быть 7. Теперь давайте отметим плитки, которые можно использовать на пути, с помощью O, плитки, которые нельзя использовать, и X, начальную точку с помощью S и цель с помощью E.

X X X X X X X
X O O E S O O
X O O O O O O

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

X X X X X X X
X O O E S O O
X X O O O X O

На случай, если это будет актуально, я разрабатываю эту настольную игру на C #.

Что касается максимального расстояния, вот диапазон, в котором оно будет находиться. Игрок бросает кубик и получает число 1-6. Если игрок получает 6, он снова бросает кости, а если он получает еще 6, снова и снова, пока он не получит 6. Расстояние - это полученное число плюс количество поднятых игроком предметов, которые теоретически могут быть поднимитесь до 8, но обычно будет 0-3, мааайбе 4.

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


person Bikonja    schedule 20.09.2012    source источник
comment
Обратите внимание, что эта проблема является NP-полной путем сведения к проблеме гамильтонова пути. Прочтите также ответ здесь.   -  person Haile    schedule 20.09.2012
comment
@Haile: Проблема является NP-полной, но вы должны быть немного осторожнее здесь, поскольку графики в задаче немного ограничены, и вам нужно уменьшить каждую проблему гамильтонова пути для действительное сокращение. При этом графы в задаче представляют собой сеточные графы, на которых поиск гамильтоновых путей является NP-полным.   -  person Nabb    schedule 20.09.2012
comment
@ Набб, ты абсолютно прав.   -  person Haile    schedule 20.09.2012


Ответы (4)


Поскольку он является NP-полным, как указал Хейл, вот эвристика на случай, если ваша проблема достаточно мала:

  • Найдите полуострова (т.е. части графа, соединенные с остальными только одним узлом), которые не содержат S и E, и удалите их.
  • Найдите кратчайший путь P от S до E. Если n меньше len(P), решения нет.
  • Теперь выполните поиск в глубину от S до E, используя следующую эвристику, чтобы выбрать, какой узел копать первым. Пусть A будет текущим тайлом в поиске в глубину. В евклидовой геометрии спроецируйте положение A на линию (SE) и назовите эту точку A'. Постарайтесь, чтобы соотношение len(current path) / n было близко к len([SA']) / len([SE]). Или, лучше, каким-то образом «спроецируйте» A на путь P, чтобы получить A'', и сохраните соотношение len(current path) / n, близкое к len([SA''] along P) / len(P).

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

person jrouquie    schedule 20.09.2012
comment
Спасибо всем, все ваши ответы дали мне общее представление о том, как подойти к проблеме. Джруки, ваше решение поразило меня больше всего, поэтому я постараюсь реализовать его (сейчас не дома, поэтому не могу сделать это сейчас) и посмотрю, как и будет ли оно работать. Я не уверен, что из себя представляет достаточно маленькое, но я отредактирую вопрос, какие будут расстояния. - person Bikonja; 20.09.2012
comment
Не забудьте остановить поиск на глубине n, как написал ларсманс. - person jrouquie; 20.09.2012

Поскольку у вас есть проблема, когда каждый шаг стоит 1, простой вариант поиска в глубину называется depth- Ограниченный поиск сможет найти нужный вам путь. Наивная версия на Python:

def dls(path, goal, depth):
    last = path[-1]
    if len(path) == depth:
        if last == goal:
            return path
    else:
        for n in neighbors(last):
            if allowed(n) and n not in path:
                path.append(n)
                solution = dls(path, depth)
                if solution:
                    return solution
                path.pop()

# call as:
dls([start], goal, depth)

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

Russell & Norvig - исчерпывающий учебник по алгоритмам такого типа.

person Fred Foo    schedule 20.09.2012
comment
Вы забыли проверить, действительно ли путь достигает цели: if path[-1]==goal: return path if len(path)==depth else None \ elif len(path) < depth: ... - person tobias_k; 20.09.2012

Если бы для этого был быстрый алгоритм, вы могли бы подключить number of nodes = n, и алгоритм быстро сообщал бы вам, есть ли гамильтониан Путь. Поскольку эта проблема является NP-полной, ваша проблема тоже.

person BlueRaja - Danny Pflughoeft    schedule 20.09.2012

Теперь, когда вопрос был обновлен с обычными значениями расстояния ...

Таким образом, на каждом временном шаге у вас есть не более 4 вариантов выбора, и не более 5 + 4 = 9 шагов. Это составляет менее 4 9 = 262 144 потенциальных пути. Сначала попробуйте грубую силу и посмотрите, как далеко это может зайти.

Также обратите внимание, что многократный бросок кости, пока вы не получите что-то другое, кроме 6, эквивалентно рисованию случайного числа от 1 до 5. Это тривиально в компьютерной игре, и такие кости есть физически (Google для изображений «5-сторонние кости»). Также распространено использование десятиугольной кости.

person jrouquie    schedule 20.09.2012
comment
Прежде всего, спасибо за ответ. Проблема в том, что ход нужно делать сразу, а не набирать 6, делать 6 и снова бросать. Хотя сейчас это спорный вопрос, как и в случае с обновленными правилами, у меня больше нет всей проблемы, поскольку у меня нет требования не наступать на одну и ту же позицию дважды. Кроме того, в игре используется 6-сторонняя игра, потому что бывают случаи, когда есть только 6 возможных результатов, хотя движение можно расширить, получив 6. Но, чтобы не углубляться в спорный вопрос, игра на самом деле существует как физическая настольная игра, Я просто делаю версию для ПК, чтобы работать с ней, поэтому я не могу изменить ее работу. - person Bikonja; 20.09.2012