• Najkrótsza odległość między dwoma punktami. Czy wiesz, dlaczego jest dalej w linii prostej niż po łuku? Określanie odległości między dwiema przecinającymi się liniami

    01.02.2022

    Po nakreśleniu kredą dwóch punktów na tablicy nauczyciel proponuje młodemu uczniowi zadanie: narysować najkrótszą drogę między obydwoma punktami.

    Student, po namyśle, pilnie rysuje między nimi krętą linię.

    - To najkrótsza droga! nauczyciel jest zaskoczony. - Kto cię tego nauczył?

    - Mój tata. Jest taksówkarzem.

    Rysunek naiwnego ucznia jest oczywiście anegdotą, ale czy nie uśmiechnąłbyś się, gdyby powiedziano ci, że kropkowany łuk na ryc. 1 to najkrótsza droga z Przylądka Dobrej Nadziei na południowy kraniec Australii!

    Jeszcze bardziej uderzające jest stwierdzenie: przedstawione na ryc. 2 podróż w obie strony z Japonii do Kanału Panamskiego jest krótsza niż linia prosta narysowana między nimi na tej samej mapie!

    Ryż. 1. Na mapie morskiej najkrótsza trasa z Przylądka Dobrej Nadziei do południowego krańca Australii nie jest oznaczona linią prostą („loksodrom”), ale krzywą („ortodomia”)


    Wszystko to wygląda na żart, ale tymczasem przed tobą są niepodważalne prawdy, dobrze znane kartografom.




    Ryż. 2. Wydaje się niewiarygodne, że zakrzywiona ścieżka łącząca Jokohamę na mapie morza z Kanałem Panamskim jest krótsza niż linia prosta poprowadzona między tymi samymi punktami


    Aby wyjaśnić tę kwestię, trzeba będzie powiedzieć kilka słów o mapach w ogóle, a w szczególności o mapach morskich. Odwzorowanie części powierzchni Ziemi na papierze nie jest zadaniem łatwym, nawet w zasadzie, ponieważ Ziemia jest kulą, a wiadomo, że żadna część powierzchni kuli nie może być rozłożona na płaszczyźnie bez zagięć i pęknięć. Mimowolnie trzeba pogodzić się z nieuniknionymi zniekształceniami na mapach. Wymyślono wiele sposobów rysowania map, ale wszystkie mapy nie są wolne od wad: niektóre mają zniekształcenia jednego rodzaju, inne innego rodzaju, ale nie ma w ogóle map bez zniekształceń.

    Żeglarze posługują się mapami narysowanymi według metody starego holenderskiego kartografa i matematyka z XVI wieku. Merkatora. Ta metoda nazywa się projekcją Mercatora. Mapę morską łatwo rozpoznać po jej prostokątnej siatce: południki są pokazane na niej jako seria równoległych linii prostych; okręgi szerokości geograficznej - również w liniach prostych prostopadłych do pierwszego (patrz ryc. 5).

    Wyobraź sobie teraz, że chcesz znaleźć najkrótszą drogę z jednego portu oceanicznego do drugiego na tym samym równoleżniku. Na oceanie wszystkie ścieżki są dostępne i zawsze można tam podróżować najkrótszą ścieżką, jeśli wiesz, jak to leży. W naszym przypadku naturalne jest myślenie, że najkrótsza ścieżka biegnie wzdłuż równoleżnika, na którym leżą oba porty: w końcu na mapie jest to linia prosta, a cóż może być krótsza niż prosta ścieżka! Ale mylimy się: droga wzdłuż równoleżnika wcale nie jest najkrótsza.

    Rzeczywiście: na powierzchni kuli najkrótszą odległością między dwoma punktami jest łączący je łuk wielkiego koła. Ale koło równoległości mały koło. Łuk dużego koła jest mniej zakrzywiony niż łuk dowolnego małego koła poprowadzonego przez te same dwa punkty: większy promień odpowiada mniejszej krzywiźnie. Przeciągnij nić na globusie między naszymi dwoma punktami (por. ryc. 3); upewnisz się, że w ogóle nie leży wzdłuż równoleżnika. Rozciągnięta nić jest niekwestionowanym wskaźnikiem najkrótszej ścieżki, a jeśli nie pokrywa się z równoleżnikiem na globusie, to na mapie morza najkrótsza ścieżka nie jest oznaczona linią prostą: pamiętaj, że na takich przedstawiono okręgi równoleżników mapa liniami prostymi, każda linia, która nie pokrywa się z linią prostą, jest krzywa .



    Ryż. 3. Prosty sposób na znalezienie naprawdę najkrótszej drogi między dwoma punktami: musisz przeciągnąć nitkę na kuli ziemskiej między tymi punktami


    Po tym, co zostało powiedziane, staje się jasne, dlaczego najkrótsza ścieżka na mapie morza jest przedstawiona nie jako linia prosta, ale jako linia zakrzywiona.

    Mówią, że przy wyborze kierunku dla kolei Nikolaev (obecnie Oktyabrskaya) toczyły się niekończące się spory o to, jak ją położyć. Spory zakończyła interwencja cara Mikołaja I, który rozwiązał problem dosłownie „prosto”: połączył wzdłuż linii Petersburg z Moskwą. Gdyby zrobiono to na mapie Mercator, byłaby to żenująca niespodzianka: zamiast prostej, droga okazałaby się łukiem.

    Każdego, kto nie stroni od kalkulacji, może przekonać prosta kalkulacja, że ​​droga, która wydaje nam się na mapie zakrzywiona, jest w rzeczywistości krótsza niż ta, którą jesteśmy gotowi uznać za prostą. Niech nasze dwa porty leżą na 60. równoleżniku i dzieli je odległość 60°. (To, czy takie dwa porty rzeczywiście istnieją, jest oczywiście nieistotne dla obliczeń.)



    Ryż. 4. Do obliczenia odległości między punktami A i B na kuli po łuku równoleżnika i po łuku wielkiego koła


    Na ryc. 4 punkty O - centrum globu, AB -łuk koła szerokości geograficznej, na którym leżą porty A i B; w jej 60°. Środek kręgu szerokości geograficznej znajduje się w punkcie Z Wyobraź to sobie od środka O kuli ziemskiej jest poprowadzona przez te same porty łukiem wielkiego koła: jego promień OB = OA = R; przejdzie blisko narysowanego łuku AB, ale to nie pasuje.

    Obliczmy długość każdego łuku. Ponieważ punkty ALE oraz W leżą na szerokości 60 °, to promienie OA oraz OW pogodzić się z OS(oś kuli ziemskiej) pod kątem 30°. W prawym trójkącie ASO noga AC (=r), leżący naprzeciwko kąta 30° jest równy połowie przeciwprostokątnej JSC;

    znaczy, r=R/2 Długość łuku AB jest jedną szóstą długości okręgu szerokości geograficznej, a ponieważ ten okrąg ma połowę długości dużego okręgu (odpowiadającą połowie promienia), to długość łuku małego okręgu



    Aby teraz wyznaczyć długość łuku wielkiego okręgu narysowanego między tymi samymi punktami (czyli najkrótszej drogi między nimi), musimy znać wielkość kąta AOW. Akord JAK, odejmując łuk do 60 ° (mały okrąg), to bok sześciokąta foremnego wpisanego w ten sam mały okrąg; Dlatego AB \u003d r \u003d R / 2

    Rysowanie linii prostej od, centrum łączące O globus ze środkiem D akordy AB, zdobądź prawy trójkąt ODA, gdzie jest kąt D- prosty:

    DA= 1/2 AB i OA=R.

    sinAOD=AD: AO=R/4:R=0,25

    Stąd znajdujemy (zgodnie z tabelami):

    =14°28",5

    i stąd

    = 28 ° 57".

    Teraz nie jest trudno znaleźć pożądaną długość najkrótszej ścieżki w kilometrach. Obliczenie można uprościć, jeśli pamiętamy, że długość jednej minuty wielkiego okręgu kuli ziemskiej wynosi

    Dowiadujemy się, że ścieżka po okręgu równoleżnikowym, pokazana na mapie morza linią prostą, wynosi 3333 km, a ścieżka po dużym okręgu - po łuku na mapie - 3213 km, czyli o 120 km krótsza.

    Uzbrojony w nitkę i globus pod ręką, możesz łatwo sprawdzić poprawność naszych rysunków i upewnić się, że łuki wielkich kół naprawdę leżą tak, jak pokazano na rysunkach. Pokazano na ryc. 1 tak jakby „prosta” droga morska z Afryki do Australii to 6020 mil, a „zakręt” – 5450 mil, czyli krótsza o 570 mil, czyli 1050 km. „Bezpośrednia” trasa lotnicza na mapie morskiej z Londynu do Szanghaju przecina Morze Kaspijskie, podczas gdy naprawdę najkrótsza trasa leży na północ od Petersburga. Jest jasne, jaką rolę odgrywają te kwestie w oszczędzaniu czasu i paliwa.

    Jeśli w dobie żeglugi żeglugowej nie zawsze ceniono czas – wtedy „czas” nie był jeszcze uważany za „pieniądz”, to wraz z pojawieniem się statków parowych trzeba płacić za każdą dodatkową tonę zużytego węgla. Dlatego w naszych czasach statki nawigują po naprawdę najkrótszej ścieżce, często korzystając z map wykonanych nie w Mercatorze, ale w tzw. rzucie „centralnym”: na tych mapach łuki wielkich okręgów są przedstawione jako linie proste.

    Dlaczego więc dawni nawigatorzy używali tak zwodniczych map i wybierali niekorzystne ścieżki? Błędem jest sądzić, że w dawnych czasach nie wiedzieli oni o wskazywanej obecnie właściwości map morskich. Sprawę tłumaczy się oczywiście nie tym, ale faktem, że mapy sporządzane metodą Mercator, wraz z niedogodnościami, niosą ze sobą bardzo cenne korzyści dla żeglarzy. Taka mapa, po pierwsze, przedstawia oddzielne małe fragmenty powierzchni ziemi bez zniekształceń, z zachowaniem narożników konturu. Nie zaprzecza temu fakt, że wraz z odległością od równika wszystkie kontury są wyraźnie rozciągnięte. Na dużych szerokościach geograficznych odcinek jest tak znaczący, że mapa morza inspiruje osobę, która nie zna jej cech, całkowicie fałszywym wyobrażeniem o prawdziwej wielkości kontynentów: Grenlandia wydaje się być tej samej wielkości co Afryka na Alasce jest większa od Australii, choć Grenlandia jest 15 razy mniejsza od Afryki, a Alaska wraz z Grenlandią jest o połowę mniejsza od Australii. Ale marynarz dobrze zaznajomiony z tymi cechami mapy nie może dać się im zwieść. Toleruje je, zwłaszcza że na niewielkich obszarach mapa morza daje dokładne odwzorowanie natury (ryc. 5).

    Z drugiej strony mapa morska znacznie ułatwia rozwiązywanie zadań praktyki nawigacyjnej. Jest to jedyny rodzaj map, na których droga statku na stałym kursie jest przedstawiona jako linia prosta. Podążanie „stałym kursem” oznacza utrzymywanie niezmiennie jednego kierunku, jednego określonego „rumbu”, innymi słowy, jechanie w taki sposób, aby przecinać wszystkie południki pod równym kątem. Ale ta ścieżka („loksodrom”) może być przedstawiona jako linia prosta tylko na mapie, na której wszystkie południki są liniami prostymi równoległymi do siebie. A ponieważ na kuli ziemskiej okręgi szerokości geograficznej przecinają się z południkami pod kątem prostym, to na takiej mapie okręgi szerokości geograficznej powinny być liniami prostymi prostopadłymi do linii południków. Krótko mówiąc, docieramy właśnie do siatki współrzędnych, która stanowi charakterystyczną cechę mapy morskiej.




    Ryż. 5. Mapa morska lub Mercator kuli ziemskiej. Na takich mapach wymiary konturów oddalonych od równika są mocno przesadzone. Która na przykład jest większa: Grenlandia czy Australia? (odpowiedź w tekście)


    Upodobanie żeglarzy do map Mercator jest teraz zrozumiałe. Chcąc określić kurs, którym należy podążać, idąc do wyznaczonego portu, nawigator przykłada linijkę do punktów końcowych ścieżki i mierzy kąt, jaki tworzy z południkami. Trzymając się cały czas na otwartym morzu w tym kierunku, nawigator precyzyjnie doprowadzi statek do celu. Widać, że „loxodrom” jest wprawdzie nie najkrótszym i nie najbardziej ekonomicznym, ale pod pewnym względem bardzo wygodnym sposobem dla żeglarza. Aby dotrzeć np. z Przylądka Dobrej Nadziei na południowy kraniec Australii (patrz rys. 1), należy zawsze utrzymywać ten sam kurs S 87 °, 50". Tymczasem, aby sprowadzić statek na ten sam punkt końcowy najkrótszą drogą (wzdłuż „ ”) należy, jak widać na rysunku, zmieniać w sposób ciągły kurs statku: zacząć od kursu S 42 °, 50” i zakończyć kursem N 53 °. 50" (w tym przypadku najkrótsza droga nie jest nawet możliwa - spoczywa na lodowej ścianie Antarktydy).

    Obie ścieżki - wzdłuż „loksodromu” i wzdłuż „ortodromii” - pokrywają się tylko wtedy, gdy ścieżka po wielkim okręgu jest przedstawiona na mapie morza jako linia prosta: podczas poruszania się wzdłuż równika lub wzdłuż południka. We wszystkich innych przypadkach te ścieżki są różne.

    (Geometria opisowa)
  • CD (CXDX, C2D2) wyświetlane jako kropka C5 = D5 A5B5 równa się...
    (Geometria opisowa)
  • Określanie odległości między dwiema równoległymi płaszczyznami
    Określanie odległości między dwiema równoległymi płaszczyznami w pozycji ogólnej 01| X wygodnie jest sprowadzić go do problemu określenia odległości między tymi samymi dwiema płaszczyznami, przekształconej w położenie wystających. W tym przypadku odległość między płaszczyznami jest definiowana jako prostopadła między liniami, ...
    (Geometria opisowa)
  • Określanie odległości między dwiema przecinającymi się liniami
    Chcąc wyznaczyć najkrótszą odległość między dwiema przecinającymi się liniami, trzeba dwukrotnie zmienić układ płaszczyzn rzutowania. Rozwiązując ten problem, bezpośredni CD (CXDX, C2D2) wyświetlane jako kropka C5 = D5(ryc. 198). Odległość od tego punktu do rzutu A5B5 równa się...
    (Geometria opisowa)
  • Kąt między dwiema przecinającymi się liniami prostymi
    Jest to kąt między dwiema przecinającymi się liniami równoległymi do danych. Zatem to zadanie jest podobne do poprzedniego. Aby go rozwiązać, należy wziąć dowolny punkt i narysować przez niego dwie proste, równoległe do podanych linii skośnych i za pomocą przekształceń rzutowych określić żądany kąt....
    (Podstawy geometrii wykreślnej. Krótki kurs i zbiór problemów.)
  • Określanie odległości między dwiema równoległymi liniami
    Problem rozwiązuje metoda podwójnej wymiany płaszczyzn rzutowania. W końcowej fazie jedna z płaszczyzn rzutowania musi być prostopadła do jednej z przecinających się linii. Następnie najkrótszą odległość między nimi określa wartość odcinka prostopadłego do drugiej linii skosu (ryc. 199)....
    (Geometria opisowa)
  • Ścieżka wzdłuż kropkowanej linii na rysunku jest krótsza niż ścieżka wzdłuż linii ciągłej. A teraz trochę bardziej szczegółowo na przykładzie szlaków morskich:

    Jeśli płyniemy stałym kursem, to trajektorią statku na powierzchni ziemi będzie krzywa, zwana w matematyce logarytmicznyspirala.

    W nawigacji ta złożona linia o podwójnej krzywiźnie nazywa się loksodromia, co po grecku oznacza „bieg ukośny”.

    Jednak najkrótszą odległość między dwoma punktami na kuli ziemskiej mierzy się po łuku wielkiego koła.

    Łuk wielkiego koła uzyskuje się jako ślad z przecięcia powierzchni ziemi z płaszczyzną przechodzącą przez środek Ziemi, wziętą jako kula.

    W nawigacji nazywa się łuk wielkiego koła wielkie koło, co oznacza „prosty bieg”. Drugą cechą wielkiego koła jest to, że przecina południki pod różnymi kątami (ryc. 29).

    Różnica odległości między dwoma punktami na powierzchni ziemi wzdłuż lokdromu i ortodromu ma praktyczne znaczenie tylko w przypadku dużych przepraw oceanicznych.

    W normalnych warunkach różnica ta jest zaniedbywana i nawigacja prowadzona jest na stałym kursie, tj. przez lokodrom.

    Aby wyprowadzić równanie, bierzemy loksodromie (ryc. 30, a) dwie kropki ALE oraz W, odległość między nimi jest po prostu niewielka. Rysując południki i równoleżnik przez nie, otrzymujemy elementarny prostokątny trójkąt kulisty ABC. W tym trójkącie kąt utworzony przez przecięcie południka i równoleżnika jest prosty, a kąt PnAB równy kursowi statku K. Katet AC reprezentuje segment południka łukowego i może być wyrażony

    gdzie R - promień Ziemi wzięty jako kula;

    Δφ - elementarny przyrost szerokości geograficznej (różnica szerokości geograficznych).

    noga południowy zachód reprezentuje segment łuku równoległy

    gdzie jesteś - promień równoleżnika;

    Δλ - elementarna różnica długości geograficznych.

    Z trójkąta OO 1 C można znaleźć, że

    Następnie w ostatecznej formie noga południowy zachód można wyrazić w ten sposób:

    Zakładając elementarny trójkąt sferyczny ABC na mieszkanie, napisz

    Po redukcji R i zastępując elementarne małe przyrosty współrzędnych przez nieskończenie małe, mamy

    Całkujemy otrzymane wyrażenie w zakresie od φ 1, λ 1 do φ 2, λ 2 rozważenie wartości tgK jako wartości stałej:

    Po prawej stronie mamy całkę tabelaryczną. Po podstawieniu jego wartości otrzymujemy równanie lokodromu na kuli

    Analiza tego równania pozwala na wyciągnięcie następujących wniosków:

    Na kursach 0 i 180 ° loxodrom zamienia się w łuk wielkiego koła - południk;

    Na kursach 90 i 270 ° loxodrom pokrywa się z równoleżnikiem;

    Loksodrom przecina każdy równoleżnik tylko raz, a każdy południk niezliczoną ilość razy. tych. spiralnie zbliżając się do bieguna, nie dociera do niego.

    Nawigacja w stałym kursie, tj. po lokodromie, chociaż nie jest to najkrótsza odległość między dwoma punktami na Ziemi, stanowi dla nawigatora znaczną wygodę.

    Wymagania dotyczące morskiej mapy nawigacyjnej można sformułować w oparciu o zalety nawigacji wzdłuż lokodromu i wyniki analizy jej równania w następujący sposób.

    1. Loksodrom, przecinający południki pod stałym kątem, należy przedstawić jako linię prostą.

    2. Rzut kartograficzny użyty do budowy map musi być konforemny, aby przebiegi, namiar i kąty na nim odpowiadały ich wartości na gruncie.

    3. Południki i równoleżniki, podobnie jak linie kursu 0, 90, 180° i 270°, muszą być wzajemnie prostopadłymi liniami prostymi.

    Najkrótsza odległość pomiędzy dwoma danymi punktami na powierzchni Ziemi, traktowana jako kula, to mniejszy z łuków wielkiego koła przechodzącego przez te punkty. Z wyjątkiem przypadku statku podążającego za południkiem lub równikiem, wielki okrąg przecina południki pod różnymi kątami. Dlatego statek płynący po takim zakręcie musi cały czas zmieniać kurs. Praktycznie wygodniej jest podążać kursem, który tworzy stały kąt z południkami i jest przedstawiony na mapie w rzucie Mercator linią prostą - lokodrom. Jednak przy dużych odległościach różnica w długości ortodromu i loxodromu osiąga znaczną wartość. Dlatego w takich przypadkach wylicza się ortodromę i zaznacza się na niej punkty pośrednie, pomiędzy którymi płyną po lokodromie.

    Rzut kartograficzny spełniający powyższe wymagania zaproponował holenderski kartograf Gerard Cramer (Mercator) w 1569 roku. Na cześć jego twórcy projekcja została nazwana Merkatora.

    A kto chce poznać jeszcze ciekawsze informacje, dowiedz się więcej Oryginalny artykuł znajduje się na stronie internetowej InfoGlaz.rf Link do artykułu, z którego pochodzi ta kopia -

    ODLEGŁOŚĆ, odległości, por. 1. Przestrzeń oddzielająca dwa punkty, przerwa między czymś. Najkrótsza odległość między dwoma punktami w linii prostej. Mieszka od nas w odległości dwóch kilometrów. „Komendant wpuścił ich z najbliższej odległości… Słownik wyjaśniający Uszakowa

    dystans- rzeczownik, s., użycie. często Morfologia: (nie) co? odległość za co? odległość, (zobacz) co? odległość niż? odległość, co? o odległości; pl. co? odległość, (nie) co? odległości, dlaczego? odległości, (zobacz) co? odległość niż? odległości... Słownik Dmitrieva

    dystans- I; por. Przestrzeń oddzielająca dwa punkty, dwa obiekty itp., odstęp między kimś, niż l. Najkrótsza rzeka między dwoma punktami. R. z domu do szkoły. Wycofaj się nad pobliską rzekę. W odległości metra ramiona wyciągnięte. Wiedz coś, poczuj coś. na… … słownik encyklopedyczny

    dystans- I; por. Zobacz też odległość a) Przestrzeń oddzielająca dwa punkty, dwa obiekty itp., odstęp między kimś, niż l. Najkrótsza odległość między dwoma punktami. Odległość z domu do szkoły. Wycofaj się na bliską odległość / nie... Słownik wielu wyrażeń

    GEOMETRIA- dział matematyki zajmujący się badaniem właściwości różnych kształtów (punktów, linii, kątów, obiektów dwuwymiarowych i trójwymiarowych), ich wielkości i względnego położenia. Dla wygody nauczania geometrię dzieli się na planimetrię i geometrię bryłową. W… … Encyklopedia Colliera

    Nawigacja*

    Nawigacja- wydział nawigacji (patrz), zakończenie prezentacji sposobów określania położenia statku na morzu za pomocą kompasu i dziennika (patrz). Aby określić miejsce statku na morzu, należy umieścić na mapie punkt, w którym aktualnie znajduje się statek.... ... Słownik encyklopedyczny F.A. Brockhaus i I.A. Efron

    COGEN- (Cohen) Hermann (1842 1918) niemiecki filozof, założyciel i najwybitniejszy przedstawiciel marburskiej szkoły neokantyzmu. Najważniejsze prace: „Teoria doświadczenia Kanta” (1885), „Uzasadnienie etyki Kanta” (1877), „Uzasadnienie estetyki Kanta” (1889), „Logika… ...

    Kant Immanuel- Życie i twórczość Kanta Immanuel Kant urodził się w 1724 r. w Królewcu (obecnie Kaliningrad) w Prusach Wschodnich. Jego ojciec był rymarzem, a matka gospodynią domową, sześcioro ich dzieci nie dożyło wieku dorosłego. Kant zawsze pamiętał swoich rodziców z ... ... Filozofia zachodnia od jej początków do współczesności

    KRYTYCZNA FILOZOFIA KANTA: DOKTRYNA ZDOLNOŚCI- (La philosophie critique de Kant: Doctrines des facultes, 1963) Deleuze'a. Opisując we wstępie metodę transcendentalną, Deleuze zauważa, że ​​Kant rozumie filozofię jako naukę o stosunku wszelkiej wiedzy do istotnych celów... ... Historia filozofii: encyklopedia

    zasada farmy- podstawowa zasada optyki geometrycznej (patrz Optyka geometryczna). Najprostszą formą F. p. jest stwierdzenie, że promień światła zawsze rozchodzi się w przestrzeni między dwoma punktami na ścieżce, po której czas jego przejścia jest krótszy niż ... Wielka radziecka encyklopedia

    Algorytm Dijkstry to algorytm grafowy wynaleziony przez holenderskiego naukowca Edsgera Dijkstrę w 1959 roku. Znajduje najkrótsze ścieżki od jednego z wierzchołków wykresu do wszystkich pozostałych. Algorytm działa tylko dla wykresów bez krawędzi o ujemnej wadze.

    Rozważ wykonanie algorytmu na przykładzie wykresu pokazanego na rysunku.

    Niech będzie wymagane znalezienie najkrótszych odległości od pierwszego wierzchołka do wszystkich pozostałych.

    Kółka oznaczają wierzchołki, linie oznaczają ścieżki między nimi (krawędzie wykresu). Numery wierzchołków są wskazane w kółkach, ich „cena” - długość ścieżki - jest wskazana nad krawędziami. Obok każdego wierzchołka zaznaczona jest czerwona etykieta - długość najkrótszej ścieżki do tego wierzchołka z wierzchołka 1.

    Pierwszy krok. Rozważmy krok w algorytmie Dijkstry dla naszego przykładu. Minimalną etykietę ma wierzchołek 1. Wierzchołki 2, 3 i 6 są jego sąsiadami.

    Z kolei pierwszym sąsiadem wierzchołka 1 jest wierzchołek 2, ponieważ długość ścieżki do niego jest minimalna. Długość ścieżki do niego przez wierzchołek 1 jest równa sumie wartości etykiety wierzchołka 1 i długości krawędzi od 1 do 2, czyli 0 + 7 = 7. To jest mniej niż aktualna etykieta wierzchołka 2, nieskończoność, więc nowa etykieta drugiego wierzchołka to 7.

    Podobną operację wykonujemy z dwoma innymi sąsiadami pierwszego wierzchołka - trzecim i szóstym.

    Wszyscy sąsiedzi węzła 1 są sprawdzani. Obecna minimalna odległość do szczytu 1 jest uważana za ostateczną i nie podlega rewizji (fakt, że rzeczywiście tak jest, po raz pierwszy udowodnił E. Dijkstra). Wykreśl go z wykresu, aby zaznaczyć, że ten wierzchołek został odwiedzony.

    Drugi krok. Krok algorytmu jest powtarzany. Ponownie znajdujemy „najbliższy” z nieodwiedzonych wierzchołków. To jest wierzchołek 2 oznaczony jako 7.

    Ponownie próbujemy zredukować etykiety sąsiadów wybranego wierzchołka, próbując przejść przez nie przez drugi wierzchołek. Sąsiadami wierzchołka 2 są wierzchołki 1, 3 i 4.

    Pierwszym (w kolejności) sąsiadem wierzchołka 2 jest wierzchołek 1. Ale został już odwiedzony, więc nic nie robimy z pierwszym wierzchołkiem.

    Następnym sąsiadem wierzchołka 2 jest wierzchołek 3, ponieważ ma minimalną etykietę wierzchołków oznaczonych jako nieodwiedzone. Jeśli przejdziesz do niego przez 2, to długość takiej ścieżki będzie równa 17 (7 + 10 = 17). Ale obecna etykieta trzeciego wierzchołka to 9, czyli mniej niż 17, więc etykieta się nie zmienia.

    Kolejnym sąsiadem wierzchołka 2 jest wierzchołek 4. Jeśli przejdziesz do niego przez drugi, to długość takiej ścieżki będzie równa sumie najkrótszej odległości do drugiego wierzchołka i odległości między wierzchołkami 2 i 4, czyli , 22 (7 + 15 = 22) . Od 22<, устанавливаем метку вершины 4 равной 22.

    Wszyscy sąsiedzi wierzchołka 2 zostali wyświetleni, zamrażamy odległość do niego i oznaczamy jako odwiedzony.

    Trzeci krok. Powtarzamy krok algorytmu wybierając wierzchołek 3. Po jego „przetworzeniu” otrzymujemy następujące wyniki:

    Następne kroki. Powtarzamy krok algorytmu dla pozostałych wierzchołków. Będą to odpowiednio wierzchołki 6, 4 i 5.

    Zakończenie wykonywania algorytmu. Algorytm kończy się, gdy nie można przetworzyć więcej wierzchołków. W tym przykładzie wszystkie wierzchołki są przekreślone, ale błędem jest zakładanie, że tak będzie w każdym przypadku - niektóre wierzchołki mogą pozostać nieprzekreślone, jeśli nie można do nich dotrzeć, tj. jeśli wykres jest odłączony. Wynik algorytmu widoczny jest na ostatnim rysunku: najkrótsza droga od wierzchołka 1 do 2 to 7, do 3 to 9, do 4 to 20, do 5 to 20, do 6 to 11.

    Implementacja algorytmu w różnych językach programowania:

    C++

    #include "stdafx.h" #include używając standardowej przestrzeni nazw; const int V=6; // Algorytm Dijkstry void Dijkstra(int GR[V][V], int st) ( int distance[V], count, index, i, u, m=st+1; bool visit[V]; for (i= 0 ja "< "<> "; cin>> start; Dijkstra(GR, start-1); system("pause>>void"); )

    Pascal

    program DijkstraAlgorithm; używacrt; constV=6; inf=100000; typ wektor=tablica liczb całkowitych; var początek: liczba całkowita; const GR: tablica liczb całkowitych=((0, 1, 4, 0, 2, 0), (0, 0, 0, 9, 0, 0), (4, 0, 0, 7, 0, 0), (0, 9, 7, 0, 0, 2), (0, 0, 0, 0, 0, 8), (0, 0, 0, 0, 0, 0)); (algorytm Dijkstry) procedura Dijkstra(GR: tablica liczb całkowitych; st: liczba całkowita); var count, index, i, u, m, min: liczba całkowita; odległość: wektor; odwiedzone: tablica wartości logicznych; początek:=st; dla i:=1 do V zacznij odległość[i]:=inf; odwiedzone[i]:=fałsz; koniec; odległość:=0; dla count:=1 do V-1 zacznij od min:=inf; dla i:=1 do V wykonaj jeśli (nie odwiedzone[i]) i (odległość[i]<=min) then begin min:=distance[i]; index:=i; end; u:=index; visited[u]:=true; for i:=1 to V do if (not visited[i]) and (GR<>0) i (odległość[u]<>inf) i (odległość[u]+GR inf then writeln(m," > ", i," = ", odległość[i]) else writeln(m," > ", i," = ", "trasa niedostępna"); koniec; (główny blok programu) begin clrscr; write("Węzeł początkowy >> "); przeczytaj(start); Dijkstra(GR, początek); koniec.

    Jawa

    import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Arrays; import java.util.StringTokenizer; klasa publiczna Rozwiązanie ( private static int INF = Integer.MAX_VALUE / 2; private int n; //liczba wierzchołków w wykresie private int m; //liczba łuków w wykresie private ArrayList przym; //lista sąsiedztwa private ArrayList waga; //waga krawędzi w digrafie użyta prywatna wartość logiczna; //tablica do przechowywania informacji o przekroczonych i nie przekazanych szczytach private int dist; //tablica do przechowywania odległości od wierzchołka początkowego //tablica przodków potrzebnych do odtworzenia najkrótszej ścieżki od wierzchołka startowego private int pred; int początek; //wierzchołek początkowy, od którego przeszukiwana jest odległość do wszystkich pozostałych private BufferedReader cin; prywatny PrintWriter cout; prywatny tokenizer StringTokenizer; //procedura uruchamiania algorytmu Dijkstry od wierzchołka startowego private void dejkstra(int s) ( dist[s] = 0; //najkrótsza odległość do wierzchołka startowego wynosi 0 for (int iter = 0; iter< n; ++iter) { int v = -1; int distV = INF; //выбираем вершину, кратчайшее расстояние до которого еще не найдено for (int i = 0; i < n; ++i) { if (used[i]) { continue; } if (distV < dist[i]) { continue; } v = i; distV = dist[i]; } //рассматриваем все дуги, исходящие из найденной вершины for (int i = 0; i < adj[v].size(); ++i) { int u = adj[v].get(i); int weightU = weight[v].get(i); //релаксация вершины if (dist[v] + weightU < dist[u]) { dist[u] = dist[v] + weightU; pred[u] = v; } } //помечаем вершину v просмотренной, до нее найдено кратчайшее расстояние used[v] = true; } } //процедура считывания входных данных с консоли private void readData() throws IOException { cin = new BufferedReader(new InputStreamReader(System.in)); cout = new PrintWriter(System.out); tokenizer = new StringTokenizer(cin.readLine()); n = Integer.parseInt(tokenizer.nextToken()); //считываем количество вершин графа m = Integer.parseInt(tokenizer.nextToken()); //считываем количество ребер графа start = Integer.parseInt(tokenizer.nextToken()) - 1; //инициализируем списка смежности графа размерности n adj = new ArrayList[n]; for (int i = 0; i < n; ++i) { adj[i] = new ArrayList(); ) //inicjowanie listy przechowującej wagi krawędzi weight = new ArrayList[n]; dla (int i = 0; i< n; ++i) { weight[i] = new ArrayList(); ) //odczytaj wykres podany przez listę krawędzi dla (int i = 0; i< m; ++i) { tokenizer = new StringTokenizer(cin.readLine()); int u = Integer.parseInt(tokenizer.nextToken()); int v = Integer.parseInt(tokenizer.nextToken()); int w = Integer.parseInt(tokenizer.nextToken()); u--; v--; adj[u].add(v); weight[u].add(w); } used = new boolean[n]; Arrays.fill(used, false); pred = new int[n]; Arrays.fill(pred, -1); dist = new int[n]; Arrays.fill(dist, INF); } //процедура восстановления кратчайшего пути по массиву предком void printWay(int v) { if (v == -1) { return; } printWay(pred[v]); cout.print((v + 1) + " "); } //процедура вывода данных в консоль private void printData() throws IOException { for (int v = 0; v < n; ++v) { if (dist[v] != INF) { cout.print(dist[v] + " "); } else { cout.print("-1 "); } } cout.println(); for (int v = 0; v < n; ++v) { cout.print((v + 1) + ": "); if (dist[v] != INF) { printWay(v); } cout.println(); } cin.close(); cout.close(); } private void run() throws IOException { readData(); dejkstra(start); printData(); cin.close(); cout.close(); } public static void main(String args) throws IOException { Solution solution = new Solution(); solution.run(); } }

    Inna opcja:

    Importuj java.io.*; import java.util.*; klasa publiczna Dijkstra ( prywatny statyczny końcowy Graph.Edge GRAPH = ( new Graph.Edge("a", "b", 7), new Graph.Edge("a", "c", 9), new Graph.Edge() "a", "f", 14), nowy Graph.Edge("b", "c", 10), nowy Graph.Edge("b", "d", 15), nowy Graph.Edge("c ", "d", 11), nowy Graph.Edge("c", "f", 2), nowy Graph.Edge("d", "e", 6), nowy Graph.Edge("e", "f", 9), ); prywatny statyczny końcowy String START = "a"; prywatny statyczny końcowy String END = "e"; public static void main(String args) ( Wykres g = nowy Wykres(WYKRES); g.dijkstra (START); g.printPath(END); //g.printAllPaths(); ) ) klasa Graph (prywatny końcowy Mapa wykres; // mapowanie nazw wierzchołków na obiekty Vertex, zbudowane ze zbioru Edges /** Jedna krawędź grafu (używana tylko przez konstruktor Graph) */ public static class Edge ( public final String v1, v2; public final int dist; public Edge(String v1, String v2, int dist) ( this.v1 = v1; this.v2 = v2; this.dist = dist; ) ) /** Jeden wierzchołek wykresu, wraz z mapowaniami do sąsiednich wierzchołków */ public static class Vertex implementuje Porównywalne ( public final String name; public int dist = Integer.MAX_VALUE; // MAX_VALUE przyjęta jako infinity public Vertex previous = null; public final Map sąsiedzi = nowa HashMap<>(); public Vertex(String name) ( this.name = name; ) private void printPath() ( if (this == this.previous) ( System.out.printf("%s", this.name); ) else if ( this.previous == null) ( System.out.printf("%s(nieosiągnięty)", this.name); ) else ( this.previous.printPath(); System.out.printf(" -> %s( %d)", this.name, this.dist); ) ) public int CompareTo(Vertex other) ( return Integer.compare(dist, other.dist); ) ) ) /** Tworzy wykres ze zbioru krawędzi * / public Graph (krawędzie krawędzi) ( graph = new HashMap<>(krawędzie.długość); //jedno przejście, aby znaleźć wszystkie wierzchołki dla (Edge e: edge) ( if (!graph.containsKey(e.v1)) graph.put(e.v1, new Vertex(e.v1)); if (!graph. zawieraKey(e.v2)) graph.put(e.v2, new Vertex(e.v2)); ) //kolejne przejście do ustawienia sąsiednich wierzchołków dla (Edge e: edge) ( graph.get(e.v1). sąsiedzi.put(graph.get(e.v2), e.dist); //graph.get(e.v2).neighbours.put(graph.get(e.v1), e.dist); // także zrób to dla wykresu nieskierowanego ) ) /** Uruchamia dijkstra przy użyciu określonego wierzchołka źródłowego */ public void dijkstra(String startName) ( if (!graph.containsKey(startName)) ( System.err.printf("Graph nie zawiera wierzchołek początkowy \"%s\"\n", startName); return; ) final Vertex source = graph.get(startName); NavigableSet q = nowy zestaw drzew<>(); // skonfiguruj wierzchołki dla (Vertex v: graph.values()) ( v.previous = v == source ? source: null; v.dist = v == source ? 0: Integer.MAX_VALUE; q.add( v);) dijkstra(q); ) /** Implementacja algorytmu dijkstry przy użyciu sterty binarnej. */ private void dijkstra(final NavigableSet q) ( Vertex u, v; while (!q.isEmpty()) ( u = q.pollFirst(); // wierzchołek o najkrótszej odległości (pierwsza iteracja zwróci źródło) if (u.dist == Integer.MAX_VALUE) break; // możemy zignorować u (i inne pozostałe wierzchołki), ponieważ są one nieosiągalne //poszukaj odległości do każdego sąsiada (Map.Entry a: u.neighbours.entrySet()) ( v = a.getKey()); //sąsiad w tej iteracji final int alternativeDist = u.dist + a.getValue(); if (alternateDist< v.dist) { // shorter path to neighbour found q.remove(v); v.dist = alternateDist; v.previous = u; q.add(v); } } } } /** Prints a path from the source to the specified vertex */ public void printPath(String endName) { if (!graph.containsKey(endName)) { System.err.printf("Graph doesn"t contain end vertex \"%s\"\n", endName); return; } graph.get(endName).printPath(); System.out.println(); } /** Prints the path from the source to every vertex (output order is not guaranteed) */ public void printAllPaths() { for (Vertex v: graph.values()) { v.printPath(); System.out.println(); } } }

    C

    #włączać #włączać #włączać //#define BIG_EXAMPLE typedef struct node_t node_t, *heap_t; typedef struct edge_t edge_t; struct edge_t ( node_t *nd; /* cel tej krawędzi */ edge_t *sibling;/* dla listy połączonej pojedynczo */ int len; /* koszt krawędzi */ ); struct node_t ( edge_t *edge; /* pojedynczo połączona lista krawędzi */ node_t *via; /* gdzie poprzedni węzeł znajduje się w najkrótszej ścieżce */ double dist; /* odległość od węzła początkowego */ char name; /* the, er , nazwa */ int heap_idx; /* link do pozycji sterty do aktualizacji odległości */ ); /* --- zarządzanie krawędziami --- */ #ifdef BIG_EXAMPLE # define BLOCK_SIZE (1024 * 32 - 1) #else # define BLOCK_SIZE 15 #endif edge_t *edge_root = 0, *e_next = 0; /* Nie przejmuj się zarządzaniem pamięcią, są one bez znaczenia.Udawaj e_next = malloc(sizeof(edge_t)) */ void add_edge(node_t *a, node_t *b, double d) ( if (e_next == edge_root) ) ( edge_root = malloc(sizeof(edge_t) * (BLOCK_SIZE + 1)); edge_root.sibling = e_next; e_next = edge_root + BLOCK_SIZE; ) --e_next; e_next->nd = b; e_next->len_next; e_next->len_next; ->sibling = a->edge; a->edge = e_next; ) void free_edges() ( for (; edge_root; edge_root = e_next) ( e_next = edge_root.sibling; free(edge_root); ) ) /* --- priorytet kolejki rzeczy --- */ heap_t *heap; int heap_len; void set_dist(node_t *nd, node_t *via, double d) ( int i, j; /* już znałem lepszą ścieżkę */ if (nd->via && d >= nd->dist) return; /* znajdź istniejący wpis sterty lub utwórz nowy */ nd->dist = d; nd->via = via; i = nd->heap_idx; if (!i) i = ++heap_len; /* upheap */ for (; i > 1 && nd->dist< heap->odległość; i = j) (kopiec[i] = kupa[j])->heap_idx = i; sterta[i] = nd; nd->heap_idx = ja; ) node_t * pop_queue() ( node_t *nd, *tmp; int i, j; if (!heap_len) return 0; /* usuń element wiodący, przeciągnij tam element ogona i w dół */ nd = sterta; tmp = sterta; for (i = 1; i< heap_len && (j = i * 2) <= heap_len; i = j) { if (j < heap_len && heap[j]->odl > sterta->odleg) j++; if (heap[j]->odleg >= tmp->odleg) przerwa; (heap[i] = sterta[j])->heap_idx = ja; ) sterta[i] = tmp; tmp->idx_sterty = ja; powrót nd; ) /* --- Dijkstra rzeczy; nieosiągalne węzły nigdy nie trafią do kolejki --- */ void calc_all(node_t *start) ( node_t *lead; edge_t *e; set_dist(start, start, 0); while ((lead = pop_queue())) for ( e = lead->edge; e; e = e->sibling) set_dist(e->nd, lead, lead->dist + e->len); ) void show_path(node_t *nd) ( if (nd-> via == nd) printf("%s", nd->name); else if (!nd->via) printf("%s(unreached)", nd->name); else ( show_path(nd-> via); printf("-> %s(%g) ", nd->name, nd->dist); ) ) int main(void) ( #ifndef BIG_EXAMPLE int i; # define N_NODES ("f" - " a" + 1) node_t *węzły = calloc(sizeof(węzeł_t), N_NODES); for (i = 0; i< N_NODES; i++) sprintf(nodes[i].name, "%c", "a" + i); # define E(a, b, c) add_edge(nodes + (a - "a"), nodes + (b - "a"), c) E("a", "b", 7); E("a", "c", 9); E("a", "f", 14); E("b", "c", 10);E("b", "d", 15);E("c", "d", 11); E("c", "f", 2); E("d", "e", 6); E("e", "f", 9); # undef E #else /* BIG_EXAMPLE */ int i, j, c; # define N_NODES 4000 node_t *nodes = calloc(sizeof(node_t), N_NODES); for (i = 0; i < N_NODES; i++) sprintf(nodes[i].name, "%d", i + 1); /* given any pair of nodes, there"s about 50% chance they are not connected; if connected, the cost is randomly chosen between 0 and 49 (inclusive! see output for consequences) */ for (i = 0; i < N_NODES; i++) { for (j = 0; j < N_NODES; j++) { /* majority of runtime is actually spent here */ if (i == j) continue; c = rand() % 100; if (c < 50) continue; add_edge(nodes + i, nodes + j, c - 50); } } #endif heap = calloc(sizeof(heap_t), N_NODES + 1); heap_len = 0; calc_all(nodes); for (i = 0; i < N_NODES; i++) { show_path(nodes + i); putchar("\n"); } #if 0 /* real programmers don"t free memories (they use Fortran) */ free_edges(); free(heap); free(nodes); #endif return 0; }

    PHP

    $krawędź, "koszt" => $krawędź); $sąsiedzi[$krawędź] = array("koniec" => $krawędź, "koszt" => $krawędź); ) $wierzchołki = array_unique($wierzchołki); foreach ($wierzchołki jako $wierzchołek) ( $odst[$wierzchołek] = INF; $poprzedni[$wierzchołek] = NULL; ) $odst[$źródło] = 0; $Q = $wierzchołki; while (count($Q) > 0) ( // TODO - Znajdź szybszy sposób na uzyskanie minimum $min = INF; foreach ($Q jako $vertex)( if ($dist[$vertex]< $min) { $min = $dist[$vertex]; $u = $vertex; } } $Q = array_diff($Q, array($u)); if ($dist[$u] == INF or $u == $target) { break; } if (isset($neighbours[$u])) { foreach ($neighbours[$u] as $arr) { $alt = $dist[$u] + $arr["cost"]; if ($alt < $dist[$arr["end"]]) { $dist[$arr["end"]] = $alt; $previous[$arr["end"]] = $u; } } } } $path = array(); $u = $target; while (isset($previous[$u])) { array_unshift($path, $u); $u = $previous[$u]; } array_unshift($path, $u); return $path; } $graph_array = array(array("a", "b", 7), array("a", "c", 9), array("a", "f", 14), array("b", "c", 10), array("b", "d", 15), array("c", "d", 11), array("c", "f", 2), array("d", "e", 6), array("e", "f", 9)); $path = dijkstra($graph_array, "a", "e"); echo "path is: ".implode(", ", $path)."\n";


    Pyton

    z kolekcji importuj namedtuple, kolejka z pprint importuj pprint jako pp inf = float("inf") Edge = namedtuple("Edge", "start, end, cost") class Graph(): def __init__(self, edge): self .edges = edge2 = self.vertices = set(sum((dla e w edge2), )) def dijkstra(self, source, dest): asercja źródła w self.vertices dist = (vertex: inf for vertex in self.vertices ) poprzedni = (wierzchołek: Brak dla wierzchołka w self.vertices) dist = 0 q = self.vertices.copy() sąsiedzi = (vertex: set() dla wierzchołka w self.vertices) dla początku, końca, koszt w self. krawędzie: sąsiedzi.add((koniec, koszt)) #pp(sąsiedzi) while q: u = min(q, key=lambda vertex: dist) q.remove(u) if dist[u] == inf lub u = = dest: break for v, koszt w sąsiednich[u]: alt = dist[u] + koszt jeśli alt< dist[v]: # Relax (u,v,a) dist[v] = alt previous[v] = u #pp(previous) s, u = deque(), dest while previous[u]: s.pushleft(u) u = previous[u] s.pushleft(u) return s graph = Graph([("a", "b", 7), ("a", "c", 9), ("a", "f", 14), ("b", "c", 10), ("b", "d", 15), ("c", "d", 11), ("c", "f", 2), ("d", "e", 6), ("e", "f", 9)]) pp(graph.dijkstra("a", "e")) Output: ["a", "c", "d", "e"]

    Podobne artykuły