Это пример того, что я хочу сделать с помощью кода. Я знаю, что вы можете использовать поиск точек перехода, чтобы без проблем добраться от зеленого узла к красному узлу или даже к A *. Но как вы рассчитываете это с перекосами.
На изображении вы можете видеть, что требуется всего 8 ходов, чтобы пройти от зеленого узла к красному узлу при выборе синего пути. Синий путь мгновенно перемещает вашу позицию от одного фиолетового узла к следующему. Пространство посередине, которое стоит 2 хода, является точкой между двумя зонами деформации, в которую вы должны перейти, чтобы добраться.
Очевидно, что быстрее идти по синему пути, поскольку вам нужно всего лишь приблизиться на половину (примерно) до желтого пути, но как мне сделать это программно?
Чтобы решить эту проблему, давайте предположим, что вокруг графика имеется множество фиолетовых «перекосов», которые вы можете использовать, И мы точно знаем, где будут искривляться каждая фиолетовая точка и где они находятся на графике.
Некоторые фиолетовые перекосы являются двунаправленными, а некоторые нет, то есть иногда вы можете входить в варп только с одной стороны, но не возвращаться после деформации.
Я подумал о решении и только пришел к выводу, что смогу вычислить проблему, проверив расстояние до каждой точки деформации (минус однонаправленные точки), а также разницу между этими точками и точками, близкими к ним. ,
Программа должна была бы каким-то образом выяснить, что выгоднее сделать второй перекос, а не идти с первого прыжка. Таким образом, вместо перемещения 6 точек, затем деформации, а затем перемещения оставшихся 8 шагов пешком (что также быстрее, чем вообще не использовать деформации), потребуется 6 ходов, а затем два шага ко второй деформации.
РЕДАКТИРОВАТЬ: я понял, что синий путь на самом деле займет 12 ходов, а не 8, но вопрос остается тем же.
источник
Ответы:
Большинство алгоритмов поиска пути определены в терминах графиков, а не в терминах сеток. На графике связь между двумя удаленными узлами в действительности не является проблемой.
Однако вы должны позаботиться о своей эвристике. Для червоточин минимальное расстояние между двумя узлами больше не является евклидовым расстоянием, и расстояние не удовлетворяет неравенству треугольника. Такая эвристика недопустима для A *. Поэтому вы не можете легко использовать A *.
Конечно, алгоритмы поиска пути, такие как Dijkstra, которые не используют эвристику, будут работать. Это больше похоже на поиск в ширину и выберет ваши червоточины без лишних усилий. Тем не менее, Дейкстра будет посещать больше узлов, чем A *, с хорошей эвристикой. (Дейкстра эквивалентен A * с
heuristic(x) = 0
.)Я думаю, что A * будет работать, если вы используете эвристику, которая рассматривает все исходящие червоточины как червоточину непосредственно до цели: эвристика может недооценивать расстояние, но никогда не должна переоценивать его. Т.е. эвристика будет:
Для очень точной эвристики вы можете (рекурсивно) добавить расстояние от конечной точки червоточины до цели или следующей червоточины. Т.е. в качестве предварительного расчета вы могли бы выполнить поиск пути на (полностью связанном) подграфе, содержащем все червоточины и цель, где расстояние между двумя узлами является их евклидовым расстоянием. Это может быть полезно, если количество червоточин намного меньше, чем количество доступных ячеек в вашей сетке. Новая эвристика будет:
Как отмечает @Caleth в комментариях, все это очень настраиваемо, и мы можем улучшить эвристику первой червоточины, не выполняя полный поиск пути через сеть червоточин, добавляя расстояние между последним выходом червоточины и целью. Поскольку мы не знаем, какой выход из червоточины будет использоваться последним, и мы не должны переоценивать, мы должны принять выход, ближайший к цели:
источник
dijkstra_heuristic(x) = 0
wormhole_path_distance
чем поиск по подграфу, и менее недооценено, чем «все выходы находятся на цели».У вас есть график с 6 вершинами на сетке с координатами:
Вы можете создать полный график по этим вершинам и назначить стоимость для каждого ребра, где стоимость
MAX( ABS( x1 - x2 ), ABS( y1 - y2 ) )
для стандартных ребер и стоимость 0 для червоточин.Это даст вам затраты (в виде матрицы смежности):
Если существуют однонаправленные деформации, то в графе (или матрице смежности) создаются только ребра, которые идут в этом направлении, но не в противоположном.
Затем вы можете использовать алгоритм Дейкстры с приоритетной очередью .
Начните с
A
и вставьте каждый соседний край в очередь с приоритетами:Формат: (путь: стоимость)
Поскольку элементы помещаются в очередь - отслеживайте минимальную стоимость для каждой вершины и проталкивайте пути в очередь, только если она дешевле, чем существующая минимальная стоимость.
Удалите первый элемент из очереди и, если его стоимость все еще соответствует минимальной стоимости, переместите все составные пути, образованные этим путем и его смежными ребрами, обратно в очередь с приоритетами (если стоимость составных путей ниже, чем существующий минимум):
Удалять:
(A-B : 7)
(A-B-A : 14)
- отвергни как дороже(A-B-C : 7)
- отвергни как за ту же цену(A-B-D : 13)
- отвергни как дороже(A-B-E : 19)
- отвергни как дороже(A-B-F : 19)
- отвергни как дорожеудалять
(A-C : 7)
(A-C-A : 14)
- отвергни как дороже(A-C-B : 7)
- отвергни как за ту же цену(A-C-D : 10)
- отвергни как за ту же цену(A-C-E : 16)
- отвергни как за ту же цену(A-C-F : 16)
- отвергни как за ту же ценуудалять
(A-D : 10)
(A-D-A : 20)
- отвергни как дороже(A-D-B : 16)
- отвергни как дороже(A-D-C : 13)
- отвергни как дороже(A-D-E : 10)
- вставь в очередь(A-D-F : 16)
- отвергни как за ту же ценуТеперь очередь будет выглядеть так:
удалять
(A-D-E : 10)
(A-D-E-A : 26)
- отвергни как дороже(A-D-E-B : 22)
- отвергни как дороже(A-D-E-C : 19)
- отвергни как дороже(A-D-E-D : 10)
- отвергни как за ту же цену(A-D-E-F : 12)
- вставь в очередьТогда очередь:
Удалите
(A-D-E-F : 12)
, найдите, что вы добрались до узла назначения по цене 12.Примечание: путь
(A-B-C-D-E-F)
,(A-C-D-E-F)
и(A-D-E-F)
все имеют одинаковую минимальную стоимость 12.источник
Установите матрицу, содержащую все вершины, и используйте алгоритм Флойд-Валленштейна или алгоритм Беллмана-Форда. Оба приведут к матрице с кратчайшими путями между всеми точками. Затем вы можете пройтись по матрице, чтобы найти кратчайший путь, соединяющий две точки. (ваша проблема такая же, как асимметричный TSP).
источник