Algorytm Lee pozwala na znalezienie najkrótszej ścieżki pomiędzy punktem początkowym, a końcowym. Wszelkie przeszkody o ile to możliwe potrafi pokonać, ale wymaga to bardzo dużej ilości pamięci i czasu. Z tego względu jego implementację ciężko znaleźć np. w grach komputerowych. Jest to jednak algorytm, który pozwala rozpocząć naukę dotyczącą szukania drogi pomiędzy dwoma punktami.
Zgodnie z algorytmem szukanie ścieżki odbywa się na planszy o kwadratowych polach. Dopuszczalne są kroki: góra, prawo, dół i lewo. W rezultacie można otrzymać ścieżkę, którą należy przejść oraz odległość jak daleko znajduje się punkt końcowy od początkowego.
Początkowo algorytm zaczyna działanie wychodząc z punktu startowego. Przyjmijmy, że na początku każdej iteracji program otrzymuje pewną listę punktów. Następnie dla każdego z tych punktów oznacza dopuszczalne kroki w każdym prawidłowym kierunku. Prawidłowy kierunek to taki, który nie prowadzi na pole z przeszkodą, albo na pole już odwiedzone. Każdy z oznaczonych punktów należy dodać na nową listę. Po zakończeniu oznaczania i przejściu do nowej iteracji za listę należy przyjąć liste punktów oznaczonych w poprzedniej iteracji. Algorytm kończy działanie, gdy pole końcowe zostanie oznaczone.
Warto jednak zauważyć, że taki algorytm sprawdza wszystkie możliwe przypadki. Jego warunkiem stopu będzie moment, gdy lista punktów oznaczonych w poprzedniej iteracji będzie pusta. Wtedy poszukiwanie drogi kończy się niepowodzeniem i należy zwrócić taką odpowiedź.
W poniższej tabeli znajdują się punkt początkowy S oraz punkt końcowy K. Przedstawione zostały kolejne etapy iteracji przechodzenia z punktu S do k. W każdej iteracji punkty od których były symulowane wszystkie możliwe kroki w danej iteracji zostały wyszczególnione niebieskim kolorem.
S | |||
---|---|---|---|
K | |||
0 | 1 | ||
1 | K | ||
0 | 1 | 2 | |
---|---|---|---|
1 | 2 | K | |
2 |
0 | 1 | 2 | 3 |
---|---|---|---|
1 | 2 | 3 | K |
2 | 3 |
0 | 1 | 2 | 3 |
1 | 2 | 3 | 4 |
---|---|---|---|
2 | 3 | 4 |
Z ostatniego schematu można odczytać, że podróż zajmuje dokładnie 4 kroki.
Tym razem na drodze algorytmu ustawmy przeszkody oznaczone █.
S | █ | K | |
---|---|---|---|
█ | █ | ||
0 | █ | K | |
1 | █ | █ | |
---|---|---|---|
0 | █ | K | |
1 | █ | █ | |
2 |
---|
0 | █ | K | |
1 | █ | █ | |
2 | 3 |
---|
0 | █ | K | |
1 | █ | █ | |
2 | 3 | 4 |
---|
0 | █ | K | |
1 | █ | 5 | █ |
---|---|---|---|
2 | 3 | 4 | 5 |
0 | █ | 6 | K |
---|---|---|---|
1 | █ | 5 | █ |
2 | 3 | 4 | 5 |
0 | █ | 6 | 7 |
---|---|---|---|
1 | █ | 5 | █ |
2 | 3 | 4 | 5 |
Tym razem najkrótsza droga wynosi 7. Warto zwrócić uwagę na fakt, że w Iteracji 6 poszukiwania zostały rozdzielone w dwóch kierunkach. Gdyby plansza została jeszcze rozszerzona w prawo lub lewo to tam również zostałyby oznaczone pola o wartości 6, a może nawet 7 (zależy czy punkt końcowy zostałby znaleziony jako pierwszy w 7 iteracji).
Poniższy program jest realizacją algorytmu Lee w celu znalezienia pomiędzy punktami. Zakłada on poprawność danych wejściowych. Po działaniu programu mapa będzie przedstawiać taki sam schemat jak wyżej zamieszczone iteracje.
Trzymanie współrzędnych w oddzielnych zmiennych może prowadzić do popełniania błędu, więc zostanie wykorzystana struktura pair, która z kolei będzie reprezentowana przez alias para.
Informacje o mapie będą przechowywane w dwuwymiarowej tablicy liczb. Wszystkie pola na które można wykonać krok będą miały wartość 0, przeszkody -1, a punkt początkowy -2.
Do szukania połączenie służy funkcja szukajPolaczenia(), która przyjmuje kolejno: mapa - mapę obszaru, w i h tj. szerokość i wysokość mapy oraz punkty start i koniec. Funkcja przedstawia sie następująco:
(2.) Utworzenie listy pól oraz (3.) określenie aktualnego numeru kroku. (4.) Początkowo na liście oznaczonych pól znajduje się tylko pole startowe. (5.) Dopóki pole końcowe nie zostanie odwiedzone: (6.) wykonaj krok i (7. - 12.) dla każdego pola spróbuj wykonać krok w każdą stronę. (13. - 14.) Jeśli nowa lista pól oznaczonych jest pusta to zwróć, że nie ma rozwiązania (wartość -1). W przeciwnym razie kontynuuj działanie i (15.) przyjmij nową listę pól zamiast starej.
W tym przypadku funkcją pomocniczą jest funkcja zmien(), która przyjmuje bardzo dużo argumentów: mapa - mapę obszaru, w i h tj. szerokość i wysokość mapy, y i x - współrzędne wykonania kroku, i - aktualny numer kroku oraz vnowy - lista oznaczonych pól w tej iteracji.
(2.) Jej zadanie sprowadza się do sprawdzenia czy pole na który wykonany został krok jest prawidłowe oraz czy można tam wykonać krok. Jeśli krok jest prawidłowy to (4.) na mapie zapisana zostaje wartość i oraz (5.) oznaczony punkt trafia na listę vnowy, aby go rozpatrzeć w kolejnej iteracji.
W celu przetestowania działania funkcji można skorzystać z poniższej funkcji main():
Wczytuje ona od użytkownika rozmiar mapy, a następnie jej schemat. Na podstawie danych wejściowych wylicza ona najkrótszą drogę pomiędzy punktami oraz pokazuje jak wygląda mapa wszystkich iteracji.
Rozmiar i szerokość mapy to dowolne liczby całkowite. Obraz mapy może składać się z x - przeszkoda, s - punkt początkowy (maksymalnie jeden) oraz k - punkt końcowy (maksymalnie jeden). Każdy pozostały znak traktowany jest jako pole na które można stanąć. Przykładowo oznaczając wolne pole kropką prawidłową mapą będzie:
Gdzie jej wysokość to 4, a szerokość 7.
W rezultacie program zwróci następującą mapę i określi odległość punktu startowego od końcowego.
Napisz program, który po otrzymaniu wyniku narysuje na ekranie jedynie ścieżkę jaką należy przejść z punktu początkowego do końcowego. Pola z przeszkodami oznacz "#", a pola wolne kropkami ".". Pola, którymi należy przejść oznacz gwiazdkami "*". Program powinien znajdować dowolną prawidłową ścieżkę: