To jest przykład tego, co chcę robić za pomocą kodu. Wiem, że możesz użyć wyszukiwania punktu skoku, aby łatwo przejść z zielonego węzła do czerwonego węzła bez problemów, a nawet A *. Ale jak to obliczyć za pomocą osnowy.
Na obrazku widać, że przejście z zielonego węzła do czerwonego węzła zajmuje tylko 8 ruchów podczas podążania niebieską ścieżką. Niebieska ścieżka natychmiast przenosi twoją pozycję z jednego fioletowego węzła do następnego. Pole pośrodku, które kosztuje 2 ruchy, to punkt między dwiema strefami wypaczenia, do którego musisz się przesunąć, aby się do niego dostać.
Wybranie niebieskiej ścieżki jest wyraźnie szybsze, ponieważ wystarczy przesunąć się w połowie (z grubsza) aż do żółtej ścieżki, ale jak mam to zrobić programowo?
Aby rozwiązać ten problem, załóżmy, że wokół wykresu znajduje się wiele fioletowych „wypaczeń”, których możesz użyć, ORAZ wiemy dokładnie, gdzie każdy purpurowy punkt wypaczy się i gdzie są na wykresie.
Niektóre fioletowe osnowy są dwukierunkowe, a niektóre nie, co oznacza, że czasami możesz wejść w osnowę tylko z jednej strony, ale nie wracać po wypaczeniu.
Zastanawiałem się nad rozwiązaniem i doszedłem do wniosku, że będę w stanie obliczyć problem, sprawdzając odległość do każdego punktu wypaczenia (minus punkty jednokierunkowe) oraz różnicę między tymi punktami a punktami w ich pobliżu .
Program musiałby w jakiś sposób dowiedzieć się, że korzystniej jest wziąć drugą warp zamiast iść od pierwszego skoku. Tak więc zamiast przesunąć 6 miejsc, następnie wypaczać, a następnie przesuwać pozostałe 8 kroków pieszo (co jest również szybsze niż w ogóle nie używanie osnowy), zajmie to 6 ruchów, a następnie dwa ruchy do drugiej osnowy.
EDYCJA: Zdałem sobie sprawę, że niebieska ścieżka zajmie 12 ruchów zamiast 8, ale pytanie pozostaje takie samo.
źródło
Odpowiedzi:
Większość algorytmów wyszukiwania ścieżek jest definiowana za pomocą wykresów, a nie siatek. Na wykresie połączenie między dwoma odległymi węzłami nie jest tak naprawdę problemem.
Musisz jednak zadbać o swoją heurystykę. W przypadku tuneli czasoprzestrzennych minimalna odległość między dwoma węzłami nie jest już odległością euklidesową, a odległość nie spełnia nierówności trójkąta. Taka heurystyka jest niedopuszczalna dla A *. Dlatego nie możesz łatwo użyć A *.
Oczywiście algorytmy wyszukiwania ścieżki, takie jak Dijkstra, które nie używają heurystyki, nadal będą działać. To bardziej przypomina wyszukiwanie z pełną szerokością i wybierze tunele czasoprzestrzenne bez dodatkowego wysiłku. Jednak Dijkstra odwiedzi więcej węzłów niż A * z dobrą heurystyką. (Dijkstra odpowiada A * z
heuristic(x) = 0
.)Myślę, że A * zadziała, jeśli użyjesz heurystyki, która traktuje wszystkie wychodzące tunele czasoprzestrzenne jako tunel czasoprzestrzenny bezpośrednio do celu: heurystyka może nie doceniać odległości, ale nigdy nie może jej przeceniać. Tj. Heurystyka byłaby:
Aby uzyskać bardzo dokładną heurystykę, możesz (rekurencyjnie) dodać odległość od punktu końcowego tunelu czasoprzestrzennego do celu lub następnego tunelu czasoprzestrzennego. Tj. Jako wstępne obliczenie można wykonać wyszukiwanie ścieżki na (całkowicie połączonym) podgrodzie zawierającym wszystkie tunele czasoprzestrzenne i cel, gdzie odległość między dwoma węzłami jest ich odległością euklidesową. Może to być korzystne, jeśli liczba tuneli czasoprzestrzennych jest znacznie mniejsza niż liczba osiągalnych komórek w sieci. Nowa heurystyka byłaby:
Jak wskazuje @Caleth w komentarzach, wszystko to jest bardzo dostrajalne i możemy poprawić heurystykę pierwszego tunelu czasoprzestrzennego bez wykonywania pełnej ścieżki wyszukiwania przez sieć tuneli czasoprzestrzennych, dodając odległość między ostatnim wyjściem tunelu czasoprzestrzennego a celem. Ponieważ nie wiemy, które wyjście z tunelu czasoprzestrzennego zostanie użyte jako ostatnie i nie możemy przeceniać, musimy założyć wyjście najbliższe celowi:
źródło
dijkstra_heuristic(x) = 0
wormhole_path_distance
niż wyszukiwanie podgrupy, a mniej niedoszacowaniem niż „wszystkie wyjścia są na cel”.Masz wykres z 6 wierzchołkami na siatce ze współrzędnymi:
Możesz wygenerować pełny wykres na tych wierzchołkach i przypisać koszt każdej krawędzi, gdzie koszt dotyczy
MAX( ABS( x1 - x2 ), ABS( y1 - y2 ) )
standardowych krawędzi, a koszt 0 dla tuneli czasoprzestrzennych.To da ci koszty (jako macierz przylegania):
Jeśli istnieją wypaczenia jednokierunkowe, wówczas należy tworzyć krawędzie na wykresie (lub macierz przylegania), które idą w tym kierunku, ale nie w przeciwnym kierunku.
Następnie możesz użyć algorytmu Dijkstry z kolejką priorytetową .
Zacznij od
A
i popchnij każdą sąsiednią krawędź do kolejki priorytetowej:Format: (ścieżka: koszt)
Gdy przedmioty są wypychane do kolejki - śledź minimalny koszt dla każdego wierzchołka i pchaj ścieżki do kolejki tylko wtedy, gdy jest on niższy niż istniejący koszt minimalny.
Usuń pierwszy element z kolejki i, jeśli jego koszt nadal odpowiada kosztowi minimalnemu, wepchnij wszystkie ścieżki złożone utworzone przez tę ścieżkę i jej sąsiednie krawędzie z powrotem do kolejki priorytetowej (jeśli ścieżki złożone mają niższy koszt niż istniejące minimum):
Usunąć:
(A-B : 7)
(A-B-A : 14)
- odrzuć jako wyższy koszt(A-B-C : 7)
- odrzuć jako taki sam koszt(A-B-D : 13)
- odrzuć jako wyższy koszt(A-B-E : 19)
- odrzuć jako wyższy koszt(A-B-F : 19)
- odrzuć jako wyższy kosztUsunąć
(A-C : 7)
(A-C-A : 14)
- odrzuć jako wyższy koszt(A-C-B : 7)
- odrzuć jako taki sam koszt(A-C-D : 10)
- odrzuć jako taki sam koszt(A-C-E : 16)
- odrzuć jako taki sam koszt(A-C-F : 16)
- odrzuć jako taki sam kosztUsunąć
(A-D : 10)
(A-D-A : 20)
- odrzuć jako wyższy koszt(A-D-B : 16)
- odrzuć jako wyższy koszt(A-D-C : 13)
- odrzuć jako wyższy koszt(A-D-E : 10)
- wstaw do kolejki(A-D-F : 16)
- odrzuć jako taki sam kosztTeraz kolejka będzie wyglądać następująco:
Usunąć
(A-D-E : 10)
(A-D-E-A : 26)
- odrzuć jako wyższy koszt(A-D-E-B : 22)
- odrzuć jako wyższy koszt(A-D-E-C : 19)
- odrzuć jako wyższy koszt(A-D-E-D : 10)
- odrzuć jako taki sam koszt(A-D-E-F : 12)
- wstaw do kolejkiKolejka to:
Usuń
(A-D-E-F : 12)
, znajdź, że dotarłeś do węzła docelowego w cenie 12.Uwaga: ścieżki
(A-B-C-D-E-F)
,(A-C-D-E-F)
i(A-D-E-F)
wszystkie mają ten sam koszt minimum 12.źródło
Skonfiguruj macierz zawierającą wszystkie wierzchołki i użyj algorytmu Floyda-Wallensteina lub algorytmu Bellmana-Forda. Oba zaowocują macierzą z najkrótszymi możliwymi ścieżkami między wszystkimi punktami. Następnie możesz iterować po macierzy, aby znaleźć najkrótszą ścieżkę łączącą dwa punkty. (twój problem jest taki sam jak asymetryczny TSP).
źródło