Ar žinote, kodėl jis yra toliau tiesioje nei lanku? Atstumo tarp dviejų lygiagrečių tiesių nustatymas Koks yra trumpiausias atstumas tarp dviejų taškų

Kelias išilgai punktyrinės linijos paveikslėlyje yra trumpesnis nei kelias išilgai ištisinės linijos. O dabar šiek tiek išsamiau apie jūrų kelių pavyzdį:

Jei naršote pastoviu kursu, tada laivo judėjimo trajektorija žemės paviršiaus bus kreivė, vadinama matematikoje logaritminisspiralė.

Navigacijoje ši sudėtinga dvigubo kreivumo linija vadinama loksodromija, kas graikų kalba reiškia „įstrižas bėgimas“.

Tačiau trumpiausias atstumas tarp dviejų Žemės rutulio taškų matuojamas išilgai didžiojo apskritimo lanko.

Didžiojo apskritimo lankas gaunamas kaip pėdsakas nuo žemės paviršiaus susikirtimo su plokštuma, kertanti žemės centrą, paimtą kaip rutulį.

Navigacijoje vadinamas didžiojo apskritimo lankas puikus ratas, o tai reiškia „tiesus bėgimas“. Antroji didžiojo apskritimo ypatybė – dienovidinius jis kerta skirtingais kampais (29 pav.).

Atstumų skirtumas tarp dviejų žemės paviršiaus taškų išilgai loksodromo ir ortodromo praktinės reikšmės turi tik didelėms vandenynų perėjoms.

Įprastomis sąlygomis šis skirtumas yra nepaisomas ir navigacija vykdoma pastoviu kursu, t.y. iki loksodromo.

Norėdami išvesti lygtį, imame loksodromijas (30 pav., a) du taškai BET ir AT, atstumas tarp jų tiesiog mažas. Nubrėžę dienovidinius ir per juos lygiagretę, gauname elementarų stačiakampį sferinį trikampį ABC.Šiame trikampyje dienovidinio ir lygiagretės susikirtimo sudarytas kampas yra stačias, o kampas PnAB lygus laivo kursui K. Katet AC reiškia dienovidinio lanko atkarpą ir gali būti išreikšta

kur R - Žemės spindulys, paimtas kaip sfera;

Δφ - elementarus platumos prieaugis (platumų skirtumas).

koja SW reiškia lygiagrečios lanko atkarpą

kur r - lygiagretės spindulys;

Δλ - elementarus ilgumų skirtumas.

Iš trikampio OO 1 C tai galima rasti

Tada galutinėje formoje koja SW galima išreikšti taip:

Darant prielaidą, kad elementarus sferinis trikampis ABC butui, rasykite

Po sumažinimo R ir pakeitę elementarius mažus koordinačių žingsnius be galo mažomis, turime

Mes integruojame gautą išraišką diapazone nuo φ 1, λ 1 iki φ 2, λ 2 tgK reikšmę laikant pastovia verte:

Dešinėje pusėje turime lentelės integralą. Pakeitę jo vertę, gauname rutulio loksodromo lygtį

Šios lygties analizė leidžia padaryti tokias išvadas:

0 ir 180 ° kurso metu loksodromas virsta didžiojo apskritimo lanku - dienovidiniu;

90 ir 270 ° kampu loksodromas sutampa su lygiagrete;

Kiekvieną lygiagretę loksodromas kerta tik vieną kartą, o kiekvieną dienovidinį – nesuskaičiuojamą skaičių kartų. tie. spirale artėdamas prie ašigalio, jo nepasiekia.

Navigacija pastoviu kursu, t. y. palei loksodromą, nors tai nėra trumpiausias atstumas tarp dviejų Žemės taškų, navigatoriui yra didelis patogumas.

Reikalavimai jūriniam navigaciniam žemėlapiui gali būti suformuluoti remiantis navigacijos palei loksodromą pranašumu ir jo lygties analizės rezultatais taip.

1. Loksodromas, kertantis dienovidinius pastoviu kampu, turėtų būti pavaizduotas kaip tiesi linija.

2. žemėlapio projekcija, naudojamas žemėlapių konstravimui, turi būti lygiakampis, kad ant jo esantys kursai, guoliai ir kampai atitiktų jų vertę ant žemės.

3. Meridianai ir lygiagretės, kaip ir kurso linijos 0, 90, 180° ir 270°, turi būti viena kitai statmenos tiesės.

Trumpiausias atstumas tarp dviejų nurodytų Žemės paviršiaus taškų, imamas kaip sfera, yra mažesnis iš didžiojo apskritimo lankų, einančių per šiuos taškus. Išskyrus laivo, einančio dienovidiniu arba pusiauju, atveju, didysis apskritimas kerta dienovidinius skirtingais kampais. Todėl laivas, einantis tokia kreive, visą laiką turi keisti kursą. Praktiškai patogiau sekti kursą, kuris sudaro pastovų kampą su dienovidiniais ir Merkatoriaus projekcijoje žemėlapyje pavaizduotas tiesia linija – loksodromu. Tačiau dideliais atstumais ortodromo ir loksodromo ilgio skirtumas pasiekia reikšmingą reikšmę. Todėl tokiais atvejais skaičiuojamas ortodromas ir jame pažymimi tarpiniai taškai, tarp kurių jie plaukia palei loksodromą.

Kartografinę projekciją, atitinkančią aukščiau nurodytus reikalavimus, 1569 m. pasiūlė olandų kartografas Gerardas Crameris (Mercator). Jos kūrėjo garbei projekcija buvo pavadinta Merkatorius.

O kas nori gauti dar daugiau įdomi informacija Sužinokite daugiau Originalus straipsnis yra svetainėje InfoGlaz.rf Nuoroda į straipsnį, iš kurio padaryta ši kopija -

DISTANCE, atstumai, žr. 1. Tarpas, skiriantis du taškus, tarpas tarp kažko. Trumpiausias atstumas tarp dviejų tiesės taškų. Gyvena nuo mūsų dviejų kilometrų atstumu. „Komendantas įleido juos artimiausiu atstumu ... Žodynas Ušakovas

atstumas- daiktavardis, s., vartosena. dažnai Morfologija: (ne) ką? atstumas už ką? atstumas, (žr.) ką? atstumas nei? atstumas, kas? apie atstumą; pl. ką? atstumas, (ne) kas? atstumai, kodėl? atstumai, (žr.) ką? atstumas nei? atstumai... Dmitrijevo žodynas

atstumas- aš; plg. Erdvė, skirianti du taškus, du objektus ir pan., tarpas tarp kažkieno, nei l. Trumpiausia upė tarp dviejų taškų. R. iš namų į mokyklą. Atsitraukite prie netoliese esančios upės. Metro atstumu ištiestos rankos. Kažką žinoti, kažką jausti. ant… … enciklopedinis žodynas

atstumas- aš; plg. taip pat žr atstumas a) Tarpas, skiriantis du taškus, du objektus ir pan., tarpas tarp kažkieno, nei l. Trumpiausias atstumas tarp dviejų taškų. Atstumas nuo namų iki mokyklos. Atsitraukite į artimą atstumą / nie ... Daugelio posakių žodynas

GEOMETRIJOS– matematikos šaka, tirianti įvairių formų (taškų, linijų, kampų, dvimačių ir trimačių objektų) savybes, jų dydį ir santykinę padėtį. Mokymo patogumui geometrija skirstoma į planimetriją ir kietąją geometriją. AT…… Collier enciklopedija

Navigacija*

Navigacija- navigacijos skyrius (žr.), baigdamas pristatymą, kaip nustatyti laivo vietą jūroje, naudojant kompasą ir žurnalą (žr.). Nustatyti laivo vietą jūroje reiškia žemėlapyje įrašyti tašką, kuriame yra laivas Šis momentas esantis…… Enciklopedinis žodynas F.A. Brockhausas ir I.A. Efronas

COGEN- (Cohen) Hermann (1842 m. 1918) vokiečių filosofas, Marburgo neokantianizmo mokyklos įkūrėjas ir ryškiausias atstovas. Pagrindiniai darbai: „Kanto patirties teorija“ (1885), „Kanto etikos pagrindimas“ (1877), „Kanto estetikos pagrindimas“ (1889), „Logika... ...

Kantas Imanuelis- Kanto gyvenimo kelias ir raštai Imanuelis Kantas gimė Karaliaučiuje (dab. Kaliningradas) Rytų Prūsijoje 1724 m. Jo tėvas buvo balnininkas, o mama – namų šeimininkė, šeši jų vaikai nesulaukė pilnametystės. Kantas visada prisimindavo savo tėvus su ...... Vakarų filosofija nuo jos ištakų iki šių dienų

KANTO KRITINĖ FILOSOFIJA: GEBĖJIMŲ DOKTRINA- (La philosophie critique de Kant: Doctrines des facultes, 1963) Deleuze'as. Įvade apibūdindamas transcendentalinį metodą, Deleuze'as pažymi, kad Kantas filosofiją supranta kaip mokslą apie visų žinių santykį su esminiais tikslais... ... Filosofijos istorija: enciklopedija

ūkio principas- pagrindinis geometrinės optikos principas (žr. Geometrinė optika). Paprasčiausia F. p. forma yra teiginys, kad šviesos spindulys visada sklinda erdvėje tarp dviejų taškų išilgai kelio, kuriuo jo praėjimo laikas yra mažesnis nei ... Didelis sovietinė enciklopedija

(Aprašomoji geometrija)
  • CD (CXDX, C2D2) parodyta kaip taškas C5 = D5 A5B5 lygu...
    (Aprašomoji geometrija)
  • Atstumo tarp dviejų lygiagrečių plokštumų nustatymas
    Atstumo tarp dviejų lygiagrečių plokštumų bendrojoje padėtyje nustatymas 01| X patogu jį redukuoti iki atstumo tarp tų pačių dviejų plokštumų, transformuotų į išsikišančių padėtį, nustatymo. Šiuo atveju atstumas tarp plokštumų apibrėžiamas kaip statmenas tarp linijų, ...
    (Aprašomoji geometrija)
  • Atstumo tarp dviejų susikertančių tiesių nustatymas
    Jei norite nustatyti trumpiausią atstumą tarp dviejų susikertančių tiesių, turite du kartus pakeisti projekcinių plokštumų sistemas. Sprendžiant šią problemą, tiesioginis CD (CXDX, C2D2) parodyta kaip taškas C5 = D5(198 pav.). Atstumas nuo šio taško iki projekcijos A5B5 lygu...
    (Aprašomoji geometrija)
  • Kampas tarp dviejų susikertančių tiesių
    Tai kampas tarp dviejų susikertančių tiesių, lygiagrečių duomenims. Taigi ši užduotis yra panaši į ankstesnę. Norėdami tai išspręsti, turite paimti savavališką tašką ir per jį nubrėžti dvi linijas, lygiagrečias nurodytoms pasvirimo linijoms, ir naudodamiesi projekcijos transformacija, nustatykite reikiamą kampą....
    (Aprašomosios geometrijos pagrindai. Trumpas kursas ir užduočių rinkinį.)
  • Atstumo tarp dviejų lygiagrečių tiesių nustatymas
    Problema išspręsta dvigubo projekcinių plokštumų pakeitimo metodu. Paskutiniame etape viena iš projekcijos plokštumų turi būti statmena vienai iš susikertančių tiesių. Tada trumpiausias atstumas tarp jų nustatomas pagal statmens kitai pasvirimo linijai atkarpos reikšmę (199 pav.).
    (Aprašomoji geometrija)
  • Lentoje kreida nubrėžęs du taškus, mokytojas siūlo jaunam mokiniui užduotį: nubrėžti trumpiausią kelią tarp abiejų taškų.

    Mokinys, pagalvojęs, stropiai brėžia tarp jų vingiuotą liniją.

    - Tai trumpiausias kelias! – nustebęs mokytojas. - Kas tave to išmokė?

    - Mano tėvas. Jis yra taksi vairuotojas.

    Naivaus moksleivio piešinys, žinoma, anekdotinis, bet ar nenusišypsotumėte, jei jums pasakytų, kad punktyrinis lankas pav. 1 yra trumpiausias kelias nuo Gerosios Vilties kyšulio iki pietinio Australijos galo!

    Dar ryškesnis yra toks teiginys: pavaizduotas Fig. 2 kelionė pirmyn ir atgal iš Japonijos į Panamos kanalą yra trumpesnė nei tiesi linija, nubrėžta tarp jų tame pačiame žemėlapyje!

    Ryžiai. 1. Įjungta jūros žemėlapis trumpiausias kelias nuo Gerosios Vilties kyšulio iki pietinio Australijos galo pažymėtas ne tiesia linija („loksodromas“), o kreive („ortodromija“)


    Visa tai atrodo kaip pokštas, tačiau prieš jus – neginčijamos tiesos, gerai žinomos kartografams.




    Ryžiai. 2. Atrodo neįtikėtina, kad lenktas kelias, jungiantis Jokohamą jūros žemėlapyje su Panamos kanalu, yra trumpesnis nei tiesi linija, nubrėžta tarp tų pačių taškų


    Norint išsiaiškinti problemą, reikės pasakyti keletą žodžių apie žemėlapius apskritai ir konkrečiai apie jūrlapius. Piešti ant popierinių žemės paviršiaus dalių net iš principo nėra lengva užduotis, nes Žemė yra sfera, ir yra žinoma, kad jokia sferinio paviršiaus dalis negali būti išdėstyta plokštumoje be raukšlių ir lūžių. Nevalingai tenka susitaikyti su neišvengiamais žemėlapių iškraipymais. Buvo išrasta daugybė žemėlapių braižymo būdų, tačiau ne visi žemėlapiai turi trūkumų: vieni turi vienokių iškraipymų, kiti kitokių, bet žemėlapių be iškraipymų visai nėra.

    Jūreiviai naudoja žemėlapius, sudarytus pagal senojo XVI amžiaus olandų kartografo ir matematiko metodą. Merkatorius. Šis metodas vadinamas Merkatoriaus projekcija. Jūros žemėlapį nesunku atpažinti pagal stačiakampį tinklelį: dienovidiniai joje pavaizduoti kaip lygiagrečių tiesių eilė; platumos apskritimai – taip pat tiesiomis tiesėmis, statmenomis pirmajai (žr. 5 pav.).

    Įsivaizduokite dabar, kad norite rasti trumpiausią kelią iš vieno vandenyno uosto į kitą toje pačioje lygiagretėje. Vandenyne yra visi takai, ir visada galima keliauti trumpiausiu keliu, jei žinai, kaip jis guli. Mūsų atveju natūralu manyti, kad trumpiausias kelias eina išilgai lygiagretės, ant kurios guli abu uostai: juk žemėlapyje tai tiesi, o kas gali būti trumpesnis už tiesią! Tačiau klystame: kelias išilgai paralelės nėra pats trumpiausias.

    Iš tiesų: rutulio paviršiuje trumpiausias atstumas tarp dviejų taškų yra juos jungiančio didžiojo apskritimo lankas. Tačiau lygiagrečių ratas mažas apskritimas. Didelio apskritimo lankas yra mažiau išlenktas nei bet kurio mažo apskritimo, nubrėžto per tuos pačius du taškus, lankas: didesnis spindulys atitinka mažesnį kreivumą. Ištraukite sriegį ant gaublio tarp dviejų mūsų taškų (plg. 3 pav.); įsitikinsite, kad jis visai nelyja lygiagrečiai. Įtempta gija – neginčijama rodyklė trumpiausias kelias, o jei nesutampa su Žemės rutulio lygiagrete, tai jūros žemėlapyje trumpiausias kelias nepažymėtas tiesia linija: atminkite, kad lygiagrečių apskritimai tokiame žemėlapyje vaizduojami tiesiomis linijomis, bet kokia linija, kuri tai daro. nesutampa su tiesia linija yra kreivė .



    Ryžiai. 3. Paprastas būdas rasti tikrai trumpiausią kelią tarp dviejų taškų: tarp šių taškų reikia ištraukti giją ant gaublio


    Po to, kas pasakyta, tampa aišku, kodėl trumpiausias kelias jūros žemėlapyje pavaizduotas ne kaip tiesi, o kaip lenkta linija.

    Jie sako, kad renkantis kryptį Nikolaevskajai (dabar Oktyabrskaya) geležinkelis kilo nesibaigiantys ginčai, kokiu būdu tai išdėstyti. Ginčus užbaigė caro Nikolajaus I įsikišimas, kuris problemą išsprendė tiesiogine prasme: Sankt Peterburgą sujungė su Maskva. Jei tai būtų padaryta Mercator žemėlapyje, tai būtų gėdinga staigmena: vietoj tiesios kelias būtų buvęs kreivė.

    Kiekvienas, kuris nevengia skaičiavimų, gali įsitikinti paprastu skaičiavimu, kad kelias, kuris mums atrodo lenktas žemėlapyje, iš tikrųjų yra trumpesnis nei tas, kurį esame pasirengę laikyti tiesiu. Tegul mūsų du uostai yra 60-oje lygiagretėje ir yra atskirti 60° atstumu. (Žinoma, skaičiuojant nesvarbu, ar tokie du uostai iš tikrųjų egzistuoja.)



    Ryžiai. 4. Atstumų tarp rutulio taškų A ir B išilgai lygiagretės lanko ir didžiojo apskritimo lanko skaičiavimui.


    Ant pav. 4 taškas O - centras pasaulis, AB - platumos apskritimo, kuriame yra uostai, lankas A ir B; in jos 60°. Platumos apskritimo centras yra taške NUOĮsivaizduokite tai iš centro O per tuos pačius uostus nubrėžtas didysis apskritimo lankas: jo spindulys OB = OA = R; jis praeis arti nubrėžto lanko AB, bet nesutampa.

    Apskaičiuokime kiekvieno lanko ilgį. Nuo taškų BET ir AT guli 60° platumoje, tada spinduliai OA ir OV susitaikyti su OS(gaublio ašis) 30° kampu. Stačiakampiame trikampyje ASO koja kintamoji srovė (=r), esantis priešais 30° kampą yra lygus pusei hipotenuzės UAB;

    reiškia, r=R/2 Arkos ilgis AB yra viena šeštoji platumos apskritimo ilgio, o kadangi šis apskritimas turi pusę didžiojo apskritimo ilgio (atitinka pusę spindulio), tai mažojo apskritimo lanko ilgis



    Norėdami dabar nustatyti didžiojo apskritimo, nubrėžto tarp tų pačių taškų, lanko ilgį (t. y. trumpiausią kelią tarp jų), turime žinoti kampo dydį AOW. Akordas AS, atėmus lanką iki 60 ° (mažas apskritimas), yra taisyklingo šešiakampio, įbrėžto į tą patį mažą apskritimą, kraštinė; Štai kodėl AB \u003d r \u003d R / 2

    Tiesios linijos brėžimas od, jungiamasis centras OŽemės rutulys su viduriu D akordai AB, gauti statųjį trikampį ODA, kur kampas D- tiesiai:

    DA = 1/2 AB ir OA = R.

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

    Iš čia randame (pagal lenteles):

    =14°28",5

    taigi

    = 28°57".

    Dabar nesunku rasti norimą trumpiausio kelio ilgį kilometrais. Skaičiavimą galima supaprastinti, jei prisiminsime, kad didžiojo Žemės rutulio minutės ilgis yra

    Sužinome, kad kelias palei platumos ratą, pavaizduotas jūros žemėlapyje tiesia linija, yra 3333 km, o takas didžiuoju apskritimu - išilgai kreivės žemėlapyje - 3213 km, t.y. 120 km trumpesnis.

    Apsiginklavę siūlu ir gaubliu po ranka, galite lengvai patikrinti mūsų brėžinių teisingumą ir įsitikinti, kad didžiųjų apskritimų lankai tikrai yra taip, kaip parodyta brėžiniuose. Pavaizduota fig. 1 tarsi „tiesus“ jūros kelias iš Afrikos į Australiją yra 6020 mylių, o „kreivė“ – 5450 mylių, t.y. trumpesnis 570 mylių arba 1050 km. „Tiesioginis“ oro maršrutas jūrų žemėlapyje iš Londono į Šanchajų kerta Kaspijos jūrą, o išties trumpiausias maršrutas yra į šiaurę nuo Sankt Peterburgo. Aišku, kokį vaidmenį šios problemos atlieka taupant laiką ir degalus.

    Jei burlaivių laivybos epochoje laikas ne visada buvo vertinamas – tada „laikas“ dar nebuvo laikomas „pinigais“, tai atsiradus garo laivams, tenka mokėti už kiekvieną papildomą sunaudotą anglies toną. Būtent todėl šiandien laivai plaukia išties trumpiausiu maršrutu, dažnai naudodami žemėlapius, padarytus ne Merkatoriuje, o vadinamojoje „centrinėje“ projekcijoje: šiuose žemėlapiuose didžiųjų apskritimų lankai vaizduojami kaip tiesios linijos.

    Kodėl tuomet buvę šturmanai naudojo tokius apgaulingus žemėlapius ir rinkosi nepalankius kelius? Klaidinga manyti, kad senais laikais jie nežinojo apie dabar nurodytą jūrų žemėlapių ypatybę. Reikalas paaiškinamas, žinoma, ne tuo, o tuo, kad pagal Merkatoriaus metodą braižyti žemėlapiai kartu su nepatogumais jūrininkams turi labai vertingos naudos. Tokiame žemėlapyje, pirma, vaizduojamos atskiros nedidelės žemės paviršiaus dalys be iškraipymų, išsaugant kontūro kampus. Tam neprieštarauja faktas, kad esant atstumui nuo pusiaujo, visi kontūrai pastebimai ištempti. Aukštose platumose ruožas yra toks reikšmingas, kad jūros žemėlapis įkvepia žmogų, nepažįstantį jo savybių, visiškai klaidingą supratimą apie tikrąjį žemynų dydį: Grenlandija atrodo tokio pat dydžio kaip Afrika ir Aliaska. yra didesnė už Australiją, nors Grenlandija yra 15 kartų mažesnė už Afriką, o Aliaska kartu su Grenlandija yra perpus mažesnė už Australiją. Tačiau jūreivis, gerai susipažinęs su šiomis diagramos ypatybėmis, negali būti jų suklaidintas. Jis toleruoja juos, ypač todėl, kad nedideliuose plotuose jūros žemėlapis tiksliai atvaizduoja gamtą (5 pav.).

    Kita vertus, jūrų žemėlapis labai palengvina navigacijos praktikos uždavinių sprendimą. Tai vienintelis žemėlapis, kuriame laivo, judančio pastoviu kursu, kelias vaizduojamas kaip tiesi linija. Eiti „nuolatiniu kursu“ reiškia nuolat laikytis vienos krypties, vieno apibrėžto „rumbo“, kitaip tariant, eiti taip, kad visi dienovidiniai būtų kertami vienodu kampu. Bet šis kelias („loksodromas“) gali būti pavaizduotas kaip tiesi linija tik žemėlapyje, kuriame visi dienovidiniai yra tiesios linijos, lygiagrečios viena kitai. Ir kadangi Žemės rutulyje platumos apskritimai kertasi su dienovidiniais stačiu kampu, tai tokiame žemėlapyje platumos apskritimai turėtų būti tiesios linijos, statmenos dienovidinių linijoms. Trumpai tariant, mes tiksliai pasiekiame koordinačių tinklelį, kuris yra būdingas jūros žemėlapio bruožas.




    Ryžiai. 5. Jūrinis arba Mercator Žemės rutulio žemėlapis. Tokiuose žemėlapiuose kontūrų, esančių toli nuo pusiaujo, matmenys yra labai perdėti. Kuris, pavyzdžiui, didesnis: Grenlandija ar Australija? (atsakymas tekstu)


    Jau suprantamas jūreivių polinkis į Mercator žemėlapius. Norėdamas nustatyti kursą, kurio reikia laikytis einant į nurodytą uostą, navigatorius pritaiko liniuotę į galinius tako taškus ir išmatuoja kampą, kurį ji daro su dienovidiniais. Visą laiką laikydamas atviroje jūroje šia kryptimi, navigatorius tiksliai nuves laivą į tikslą. Matote, kad „loksodromas“ yra, nors ir ne pats trumpiausias ir ne pats ekonomiškiausias, bet tam tikra prasme labai patogus būdas buriuotojui. Norint pasiekti, pavyzdžiui, nuo Gerosios Vilties kyšulio iki pietų Australijos pakraščio (žr. 1 pav.), visada reikia laikytis to paties kurso S 87 °,50 ". Tuo tarpu norint atplukdyti laivą į tą patį galutinis taškas trumpiausias kelias(pagal "ortodromiją"), būtina, kaip matyti iš paveikslo, nuolat keisti laivo kursą: pradėti nuo kurso S 42 °,50 "ir baigti kursu N 53 °,50 “ (šiuo atveju net neįmanomas trumpiausias kelias – į Antarkties ledo sieną).

    Abu takai – palei „loksodromą“ ir palei „ortodromą“ – sutampa tik tada, kai dideliame apskritime kelias jūros žemėlapyje pavaizduotas kaip tiesi linija: judant pusiauju arba dienovidiniu. Visais kitais atvejais šie keliai skiriasi.

    Dijkstros algoritmas yra grafinis algoritmas, kurį 1959 m. išrado olandų mokslininkas Edsgeris Dijkstra. Suranda trumpiausius kelius nuo vienos iš grafo viršūnių iki visų kitų. Algoritmas veikia tik grafams be neigiamo svorio briaunų.

    Apsvarstykite algoritmo vykdymą paveikslėlyje parodyto grafiko pavyzdyje.

    Tegul reikalaujama rasti trumpiausius atstumus nuo 1-osios viršūnės iki visų kitų.

    Apskritimai žymi viršūnes, linijos – takus tarp jų (grafiko briaunas). Viršūnių skaičiai nurodyti apskritimuose, virš kraštų – jų „kaina“ – tako ilgis. Šalia kiekvienos viršūnės pažymėta raudona etiketė – trumpiausio kelio ilgis į šią viršūnę nuo 1 viršūnės.

    Pirmas žingsnis. Apsvarstykite Dijkstros algoritmo žingsnį mūsų pavyzdyje. Viršūnė 1 turi minimalią etiketę. 2, 3 ir 6 viršūnės yra jos kaimynės.

    Pirmoji 1 viršūnės kaimynė savo ruožtu yra viršūnė 2, nes kelio į ją ilgis yra minimalus. Kelio ilgis į jį per viršūnę 1 yra lygus 1 viršūnės etiketės vertės ir briaunos, einančios nuo 1 iki 2, ilgio sumai, ty 0 + 7 = 7. Tai yra mažesnė už dabartinė 2 viršūnės etiketė, begalybė, todėl naujoji 2 viršūnės etiketė yra 7.

    Panašią operaciją atliekame su dar dviem 1-osios viršūnės kaimynais – 3 ir 6.

    Visi 1 mazgo kaimynai yra patikrinti. Dabartinis minimalus atstumas iki 1 smailės yra laikomas galutiniu ir nėra tikslinamas (tai, kad taip tikrai yra, pirmasis įrodė E. Dijkstra). Išbraukite jį iš grafiko, kad pažymėtumėte, jog ši viršūnė buvo aplankyta.

    Antras žingsnis. Algoritmo žingsnis kartojamas. Vėl randame „artimiausią“ iš neaplankytų viršūnių. Tai yra 2 viršūnė, pažymėta 7.

    Vėl bandome sumažinti pasirinktos viršūnės kaimynų etiketes, bandydami jas pereiti per 2-ąją viršūnę. 2 viršūnės kaimynės yra 1, 3 ir 4 viršūnės.

    Pirmasis (eilės tvarka) 2 viršūnės kaimynas yra viršūnė 1. Bet ji jau buvo aplankyta, todėl su 1 viršūne nieko nedarome.

    Kitas 2 viršūnės kaimynas yra 3 viršūnė, nes joje yra mažiausia viršūnių etiketė, pažymėta kaip neaplankyta. Jei einate į jį per 2, tada tokio kelio ilgis bus lygus 17 (7 + 10 = 17). Tačiau dabartinė trečiosios viršūnės etiketė yra 9, tai yra mažesnė nei 17, todėl etiketė nesikeičia.

    Kitas 2 viršūnės kaimynas yra viršūnė 4. Jei į ją eisite per 2-ąją, tai tokio kelio ilgis bus lygus trumpiausio atstumo iki 2-osios viršūnės ir atstumo tarp 2 ir 4 viršūnių sumai, tai yra , 22 (7 + 15 = 22) . Nuo 22<, устанавливаем метку вершины 4 равной 22.

    Visi 2 viršūnės kaimynai peržiūrėti, atstumą iki jos užfiksuojame ir pažymime kaip aplankytą.

    Trečias žingsnis. Algoritmo žingsnį kartojame pasirinkdami viršūnę 3. Ją „apdorojus“ gauname tokius rezultatus:

    Tolesni žingsniai. Likusioms viršūnėms pakartojame algoritmo žingsnį. Tai bus atitinkamai 6, 4 ir 5 viršūnės.

    Algoritmo vykdymo užbaigimas. Algoritmas baigiasi, kai nebegalima apdoroti viršūnių. Šiame pavyzdyje visos viršūnės yra perbrauktos, tačiau klaidinga manyti, kad taip bus bet kuriame pavyzdyje – kai kurios viršūnės gali likti neperbrauktos, jei jų nepavyksta pasiekti, t.y. jei grafikas yra atjungtas. Algoritmo rezultatas matomas paskutiniame paveikslėlyje: trumpiausias kelias iš viršūnės 1 į 2 yra 7, iki 3 yra 9, iki 4 yra 20, iki 5 yra 20, iki 6 yra 11.

    Algoritmo įgyvendinimas įvairiomis programavimo kalbomis:

    C++

    #include "stdafx.h" #include naudojant vardų erdvę std; const int V=6; // Dijkstra algoritmas void Dijkstra(int GR[V][V], int st) ( int atstumas[V], skaičius, indeksas, i, u, m=st+1; bool aplankyta[V]; for (i= 0 i "< "<> "; cin>>start; Dijkstra(GR, start-1); system("pause>>void"); )

    Paskalis

    programa DijkstraAlgoritm; usescrt; constV=6; inf=100000; tipo vektorius=sveiko skaičiaus masyvas; var pradžia: sveikasis skaičius; const GR: sveikųjų skaičių masyvas=((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)); (Dijkstros algoritmas) procedura Dijkstra(GR: masyvas sveikasis skaičius; st: integer); var skaičius, indeksas, i, u, m, min: sveikasis skaičius; atstumas: vektorius; aplankyta: loginio masyvas; pradžia:=st; jei i:=1 iki V – pradžios atstumas[i]:=inf; aplankytas[i]:=false; pabaiga; atstumas:=0; count:=1 iki V-1 pradėkite min:=inf; už i:=1 iki V do if (nelankyta[i]) ir (atstumas[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) ir (atstumas[u]<>inf) ir (atstumas[u]+GR inf then writeln(m," > ", i," = ", distance[i]) else writeln(m," > ", i," = ", "maršrutas nepasiekiamas"); pabaiga; (pagrindinis programos blokas) begin clrscr; write("Pradžios mazgas >> "); skaityti (pradėti); Dijkstra(GR, pradžia); pabaiga.

    Java

    importuoti java.io.BufferedReader; importuoti java.io.IOException; importuoti java.io.InputStreamReader; importuoti java.io.PrintWriter; importuoti java.util.ArrayList; importuoti java.util.Arrays; importuoti java.util.StringTokenenizer; public class Sprendimas ( private static int INF = Integer.MAX_VALUE / 2; private int n; //viršūnių skaičius digrafe private int m; //lankų skaičius digrafe private ArrayList adj; //gretumų sąrašas privatus ArrayList svoris; //Krašto svoris digrafe naudojamas privatus loginis dydis; //masyvas, skirtas saugoti informaciją apie praleistas ir nepraleistas smailes private int dist; //masyvas atstumui nuo pradinės viršūnės saugoti //protėvių masyvas, reikalingas norint atkurti trumpiausią kelią nuo pradinės viršūnės private int pred; int start; //pradžios viršūnė, nuo kurios atstumas iki visų kitų ieškomas privatus BufferedReader cin; privatus PrintWriter cout; privatus StringTokenizer žetonas; //procedūra paleisti Dijkstra algoritmą nuo pradinės viršūnės private void dejkstra(int s) ( dist[s] = 0; //trumpiausias atstumas iki pradinės viršūnės yra 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(); ) //sąrašo, kuriame saugomi briaunų svoriai, inicijavimas weight = new ArrayList[n]; už (int i = 0; i< n; ++i) { weight[i] = new ArrayList(); ) //perskaitykite grafiką, pateiktą pagal briaunų sąrašą (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(); } }

    Kitas variantas:

    Importuoti java.io.*; importuoti java.util.*; public class Dijkstra ( privatus statinis galutinis Graph.Edge GRAPH = ( new Graph.Edge("a", "b", 7), new Graph.Edge("a", "c", 9), new Graph.Edge( "a", "f", 14), naujas Graph.Edge("b", "c", 10), naujas Graph.Edge("b", "d", 15), naujas Graph.Edge("c" ", "d", 11), naujas Graph.Edge("c", "f", 2), naujas Graph.Edge("d", "e", 6), naujas Graph.Edge("e", "f", 9), ); privati ​​statinė galutinė eilutė START = "a"; privati ​​statinė galutinė eilutė END = "e"; vieša statinė galia main (String args) ( grafikas g = naujas grafikas(GRAPH); g.dijkstra (START); g.printPath(END); //g.printAllPaths(); ) ) klasės grafikas (privatus galutinis žemėlapis grafikas; // viršūnių pavadinimų susiejimas su viršūnių objektais, sudarytas iš briaunų rinkinio /** Vienas grafo kraštas (naudojamas tik Graph konstruktoriaus) */ 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; ) ) /** Viena grafiko viršūnė su gretimų viršūnių atvaizdais */ viešoji statinė klasė „Vertex“ padargai Palyginami (viešas galutinis eilutės pavadinimas; viešasis int dist = Sveikasis skaičius.MAX_VALUE; // MAX_VALUE laikoma begalybe vieša viršūnė ankstesnė = null; viešas galutinis žemėlapis kaimynai = naujas 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(nepasiekta)", this.name); ) else ( this.previous.printPath(); System.out.printf(" -> %s() %d)", this.name, this.dist); ) ) public int palygintiTo(viršūnė kita) ( grąžinti Integer.palyginti(dist, other.dist); ) ) /** Sukuria grafiką iš briaunų rinkinio * / viešas grafikas (kraštų kraštai) ( grafikas = naujas HashMap<>(kraštai.ilgis); //vienu žingsniu, kad surastumėte visas (Edge e: briaunos) viršūnes ( if (!graph.containsKey(e.v1)) graph.put(e.v1, new Vertex(e.v1)); if (!graph. includeKey(e.v2)) graph.put(e.v2, new Vertex(e.v2)); ) //dar vienas veiksmas, norint nustatyti gretimas viršūnes (Edge e: briaunos) ( graph.get(e.v1). kaimynai.put(grafas.get(e.v2), e.dist); //graph.get(e.v2).neighbours.put(graph.get(e.v1), e.dist); // taip pat darykite tai nenukreiptam grafikui ) ) /** Vykdo dijkstra naudojant nurodytą šaltinio viršūnę */ public void dijkstra(String startName) ( if (!graph.containsKey(startName)) ( System.err.printf("Grafas neveikia yra pradžios viršūnė \"%s\"\n", startName); grįžti; ) galutinis viršūnės šaltinis = graph.get(startName); NavigableSet q = naujas medžio rinkinys<>(); // viršūnių nustatymas (Vertex v: graph.values()) ( v.previous = v == šaltinis ? šaltinis: null; v.dist = v == šaltinis ? 0: Integer.MAX_VALUE; q.add( v); ) dijkstra(q); ) /** Dijkstra algoritmo įgyvendinimas naudojant dvejetainę krūvą. */ private void dijkstra(galutinis NavigableSet q) ( Viršūnė u, v; while (!q.isEmpty()) ( u = q.pollFirst(); // viršūnė su trumpiausiu atstumu (pirma iteracija grąžins šaltinį) if (u.dist == Integer.MAX_VALUE) pertrauka; // galime nekreipti dėmesio į u (ir visas kitas likusias viršūnes), nes jos nepasiekiamos //pažiūrėkite atstumus iki kiekvieno kaimyno (Map.Entry a: u.neighbours.entrySet()) ( v = a.getKey(); //šios iteracijos kaimynas final int alternateDist = 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

    #įtraukti #įtraukti #įtraukti //#define BIG_EXAMPLE typedef struct mazgas_t mazgas_t, *heap_t; typedef struktūra kraštas_t kraštas_t; struct edge_t ( node_t *nd; /* šio krašto tikslas */ edge_t *sibling;/* atskirai susietam sąrašui */ int len; /* krašto kaina */ ); struct node_t ( kraštas_t *kraštas; /* atskirai susietas briaunų sąrašas */ node_t *per; /* kur ankstesnis mazgas yra trumpiausiu keliu */ double dist; /* atstumas nuo pradinio mazgo */ simbolio pavadinimas; /* the, er , pavadinimas */ int heap_idx /* nuoroda į krūvos padėtį, kad būtų atnaujintas atstumas */ ); /* --- briaunų valdymas --- */ #ifdef BIG_EXAMPLE # apibrėžti BLOCK_DIZE (1024 * 32 - 1) #else # apibrėžti BLOCK_SIZE 15 #endif edge_t *krašto_šaknis = 0, *e_next = 0; /* Nesirūpinkite atminties valdymo dalykais, jie yra ne tik esmė. Apsimesti e_next = malloc(sizeof(edge_t)) */ void add_edge(mazgas_t *a, node_t *b, double d) ( if (e_next == edge_root ) ( kraštas_šaknis = malloc(dydis(krašto_t) * (BLOCK_DIZE + 1)); kraštas_šaknis.sesuo = e_kitas; e_next = kraštas_šaknis + BLOCK_DIZE; ) --e_next; e_next->nd = b; e_next->len =exdt; ->brolis = a->kraštas; a->kraštas = e_kitas; ) void laisvieji_kraštai() (skirta (; kraštas_šaknis; kraštas_šaknis = e_next) ( e_next = kraštas_šaknis.brolis; laisvas(krašto_šaknis); ) ) /* --- prioriteto eilės medžiaga --- */ heap_t *heap; int heap_len; void set_dist(node_t *nd, node_t *via, double d) ( int i, j; /* jau žinojo geresnį kelią */ if (nd->per && d >= nd->dist) return; /* suraskite esamą krūvos įrašą arba sukurkite naują */ nd->dist = d; nd->via = per; i = nd->heap_idx; if (!i) i = ++heap_len; /* upheap */ for (; i > 1 && nd->dist< heap->dist; i = j) (krūva[i] = krūva[j])->krūvos_idx = i; krūva[i] = nd; nd->heap_idx = i; ) node_t * pop_queue() ( node_t *nd, *tmp; int i, j; jei (!heap_len) grąžina 0; /* pašalinkite pagrindinį elementą, patraukite ten esantį elementą ir nuleiskite */ nd = krūva; tmp = krūva; (i = 1; i< heap_len && (j = i * 2) <= heap_len; i = j) { if (j < heap_len && heap[j]->dist > heap->dist) j++; if (heap[j]->dist >= tmp->dist) break; (krūva[i] = krūva[j])->krūvos_idx = i; ) krūva[i] = tmp; tmp->heap_idx = i; grįžti nd; ) /* --- Dijkstra stuff; nepasiekiami mazgai niekada nepadarys į eilė --- */ void calc_all(mazgas_t *pradžia) ( mazgas_t *lead; edge_t *e; set_dist(pradžia, pradžia, 0); while ((lead = pop_queue())) for (e = švinas->kraštas; e; e = e->sibling) set_dist(e->nd, lead, lead->dist + e->len); ) void show_path(mazgas_t *nd) (if (nd->per == nd) printf( "%s", nd->pavadinimas); else if (!nd->via) printf("%s(nepasiekta)", nd->pavadinimas); else ( show_path(nd->via); printf("- > %s(%g) ", nd->name, nd->dist); ) ) int main(void) ( #ifndef BIG_EXAMPLE int i; # apibrėžkite N_NODES ("f" - "a" + 1) node_t * mazgai = calloc(dydis(mazgas_t), N_mazgai); 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

    $ kraštas, "kaina" => $ kraštas); $kaimynai[$kraštas] = masyvas("pabaiga" => $kraštas, "kaina" => $kraštas); ) $viršūnės = masyvas_unikalus($viršūnės); foreach ($viršūnės kaip $viršūnė) ( $dist[$vertex] = INF; $previous[$vertex] = NULL; ) $dist[$source] = 0; $Q = $viršūnės; while (count($Q) > 0) ( // TODO – Raskite greitesnį būdą gauti minimalų $min = INF; foreach ($Q kaip $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";


    Python

    iš kolekcijų importuoti namedtuple, eilę iš pprint importuoti pprint as pp inf = float("inf") Edge = namedtuple("Edge", "pradžia, pabaiga, kaina") class Graph(): def __init__(self, edges): self .edges = briaunos2 = self.vertices = set(sum(( e in edges2), )) def dijkstra(self, source, dest): patvirtinti šaltinį savyje.viršūnės dist = (viršūnė: inf viršūnei savyje.viršūnės ) previous = (viršūnė: Nėra viršūnės savyje.viršūnėse) dist = 0 q = self.vertices.copy() kaimynai = (viršūnė: set() viršūnei savyje.viršūnėse) pradžiai, pabaigai, savikainai. briaunos: kaimynai.add((pabaiga, kaina)) #pp(kaimynai) while q: u = min(q, raktas=lambda viršūnė: dist) q.remove(u) if dist[u] == inf arba u = = dest: pertrauka v, kaina kaimynuose[u]: alt = dist[u] + kaina, jei 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"]