Dana jest mapa labiryntu opisana zerami (wolne pole) i jedynkami (zajęte pole). Napisz program, który znajdzie najkrótszą drogę do dowolnego rogu mapy. Można się poruszać tylko lewo, prawo, góra i dół. Jako dane na wejściu otrzyma rozmiar planszy (w, h), zapis labiryntu w postaci macierzy zer i jedynek o podanym wcześniej rozmiarze oraz punkt startowy. Wiersze i kolumny indeksujemy od 0.
Przypuśćmy, że dana jest następująca mapa labiryntu o wymiarach 8x6.
0 | 1 | 1 | 1 | 0 | 0 | 0 | 0 |
---|---|---|---|---|---|---|---|
0 | 1 | 1 | 1 | 0 | 1 | 1 | 0 |
0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 |
1 | 1 | 1 | 0 | 1 | 0 | 0 | 1 |
1 | 1 | 1 | 0 | S | 1 | 0 | 1 |
1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 |
Pole z wartością S wskazuje na punkt początkowy (4, 4). Można z niego osiągnąć trzy rogi z czterech w następującej ilości kroków: lewy, górny w 8 krokach, prawy, górny w 9, a ostatni prawy, dolny w 10. Ostateczna odpowiedź to oczywiście 8.
W celu rozwiązania tego zadania można skorzystać z schematu przeszukiwania wszerz BFS. Mianowicie na początku na kolejkę pól wrzucane jest pole startowe. Następnie dla każdego punktu w kolejce sprawdzamy sąsiednie pola (na górze, na dole, po prawej i po lewej). Przy każdym przejściu zwiększamy aktualną odległość o 1. Jeśli zostanie napotkany róg planszy to aktualizujemy minimalną odległość do rogu o ile aktualna odległość jest mniejsza niż zapisana.
Taki algorytm będzie przeglądać wszystkie możliwe pola, ale proces ten można ograniczyć poprzez sprawdzenie czy dodawane pole do kolejki ma odległość mniejszą niż aktualne minimum. Dzięki temu nie będą sprawdzane pola, które i tak nie ma ją szans wskazać najkrótszej ścieżki. Dodatkowo należy pamiętać, że na samym początku trzeba sprawdzić czy punkt startowy nie jest w rogu. Wtedy wynikiem jest wartość 0.
Podczas przeglądania mapy będzie potrzebne zapisanie aktualnie przeglądanych pól oraz ich aktualnej odległości. Ułatwi to struktura Dane.
W tym zadaniu ważne jest, aby móc sprawdzić czy dane pole nie jest rogiem planszy. Funkcja CzyRog() odpowiada na to pytanie. Wystarczy podać rozmiar planszy oraz aktualnie przeglądaną pozycję.
W przedstawionym w dalszej częściu algorytmu program na ślepo wyznacza kolejne pola, dlatego należy sprawdzić funkcją CzyOk() czy dane pole istnieje.
Oto kod głównej funkcji SzukajDrogi(), która dla danej macierzy o rozmiarze rozmiar i danym punkcie startowym punktStart zwróci najkrótszą odległość do dowolnego rogu planszy.
Na początku algorytm sprawdza czy start nie znajduje się w rogu. W przeciwnym razie przechodzimy do inicjalizacji kolejki i umieszczamy na niej punky startowy. Deklarowane są również możliwe przesunięcia względem aktualnie wybranego punktu. Następnie dopóki kolejka nie jest pusta pobieramy pierwszy element i jeśli jest narożnikiem to aktualizujemy aktualne minimum. Potem wyliczamy sąsiednie pola i dodajemy do kolejki tylko te, które spełniają warunek.
W celu przetestowania kodu można skorzystać z poniższego fragmentu programu:
Jako dane testowe można podać następujące dane: