Знаете ли защо по права линия е по-далеч, отколкото по дъга? Определяне на разстоянието между две успоредни прави Кое е най-късото разстояние между две точки

Пътят по пунктираната линия на снимката е по-къс от пътя по плътната линия. А сега малко по-подробно на примера на морските пътища:

Ако се движите по постоянен курс, тогава траекторията на движението на кораба ще продължи земната повърхностще бъде крива, наречена в математиката логаритмиченспирала.

В навигацията тази сложна линия с двойна кривина се нарича локсодромия, което на гръцки означава "косо бягане".

Но най-късото разстояние между две точки на земното кълбо се измерва по дъгата на голяма окръжност.

Дъгата на голям кръг се получава като следа от пресечната точка на земната повърхност с равнина, минаваща през центъра на земята, взета като топка.

В навигацията голямата кръгова дъга се нарича голям кръг, което означава "прав ход". Втората особеност на големия кръг е, че той пресича меридианите под различни ъгли (фиг. 29).

Разликата в разстоянията между две точки на земната повърхност по протежение на локсодрума и ортодрума е от практическо значение само за големи пресичания на океана.

При нормални условия тази разлика се пренебрегва и навигацията се извършва по постоянен курс, т.е. от локсодрома.

За да изведем уравнението, вземаме локсодроми (фиг. 30, а) две точки НОи AT,разстоянието между тях е просто малко. Начертавайки меридиани и паралел през тях, получаваме елементарен правоъгълен сферичен триъгълник ABC.В този триъгълник ъгълът, образуван от пресечната точка на меридиана и паралела, е прав, а ъгълът ПнABравен на курса на кораба К. Катет ACпредставлява сегмент от меридианна дъга и може да се изрази

където Р - радиус на Земята, взета като сфера;

Δφ - елементарно увеличение на географската ширина (разлика на географските ширини).

крак SWпредставлява дъгова отсечка, успоредна

където r - радиус на паралела;

Δλ - елементарна разлика на дължините.

От триъгълник OO 1 C може да се намери това

След това в окончателната форма крака SWможе да се изрази така:

Приемайки елементарен сферичен триъгълник ABCза апартамент пишете

След намаление Р и заменяйки елементарни малки нараствания на координатите с безкрайно малки, имаме

Интегрираме получения израз в диапазона от φ 1, λ 1 до φ 2, λ 2 като се има предвид стойността на tgK като постоянна стойност:

От дясната страна имаме табличен интеграл. След като заместим стойността му, получаваме уравнението на локсодрома върху топката

Анализът на това уравнение ни позволява да направим следните заключения:

При курсове от 0 и 180 ° локсодромът се превръща в дъга на голям кръг - меридиан;

При курсове от 90 и 270 ° локсодромата съвпада с паралела;

Локсодромът пресича всеки паралел само веднъж и всеки меридиан безброй пъти. тези. спираловидно се приближава към полюса, не го достига.

Навигацията в постоянен курс, т.е. по локсодрума, въпреки че не е най-късото разстояние между две точки на Земята, представлява значително удобство за навигатора.

Изискванията за морска навигационна карта могат да бъдат формулирани въз основа на предимството на навигацията по протежение на локсодрума и резултатите от анализа на неговото уравнение, както следва.

1. Локсодромът, пресичащ меридианите под постоянен ъгъл, трябва да бъде изобразен като права линия.

2. картна проекция, използван за съставяне на карти, трябва да бъде равноъгълен, така че курсовете, пеленгите и ъглите върху него да съответстват на стойността им на земята.

3. Меридианите и паралелите, като линиите на курса 0, 90, 180° и 270°, трябва да бъдат взаимно перпендикулярни прави линии.

Най-късото разстояние между две дадени точки на повърхността на Земята, взета като сфера, е по-малката от дъгите на голяма окръжност, минаваща през тези точки. Освен в случай на кораб, следващ меридиан или екватор, големият кръг пресича меридианите под различни ъгли. Следователно кораб, следващ такава крива, трябва да променя курса си през цялото време. Практически по-удобно е да се следва курс, който сключва постоянен ъгъл с меридианите и се изобразява на картата в проекцията на Меркатор с права линия - локсодрома. Въпреки това, на големи разстояния разликата в дължината на ортодрома и локсодрома достига значителна стойност. Следователно в такива случаи ортодромата се изчислява и върху нея се отбелязват междинни точки, между които плуват по локсодромата.

Картографска проекция, която отговаря на горните изисквания, е предложена от холандския картограф Герард Крамер (Меркатор) през 1569 г. В чест на своя създател проекцията е наречена Меркатор.

И който иска да получи още повече интересна информацияНаучете повече Оригиналната статия е на уебсайта InfoGlaz.rfЛинк към статията, от която е направено това копие -

ДИСТАНЦИЯ, разстояния вж. 1. Пространство, разделящо две точки, празнина между нещо. Най-късото разстояние между две точки по права линия. Живее от нас на разстояние два километра. „Комендантът ги пусна на най-близкото разстояние ... РечникУшаков

разстояние- съществително, с., употреб. често Морфология: (не) какво? разстояние за какво? разстояние, (виж) какво? разстояние от? разстояние, какво? за разстоянието; мн. Какво? разстояние, (не) какво? разстояния, защо? разстояния, (виж) какво? разстояние от? разстояния... Речник на Дмитриев

разстояние- аз; вж. Пространството, разделящо две точки, два обекта и т.н., празнината между някого, отколкото l. Най-късата река между две точки. Р. от ​​вкъщи до училище. Оттеглете се до близката река. На разстояние метър, протегнати ръце. Знайте нещо, почувствайте нещо. на… … енциклопедичен речник

разстояние- аз; вж. Вижте също разстояние а) Пространството, разделящо две точки, два обекта и т.н., разликата между някого, отколкото l. Най-късото разстояние между две точки. Разстояние от дома до училище. Оттеглете се на близко разстояние / nie ... Речник на много изрази

ГЕОМЕТРИЯ- дял от математиката, който изучава свойствата на различни форми (точки, линии, ъгли, двуизмерни и триизмерни обекти), техния размер и взаимно разположение. За удобство на преподаването геометрията е разделена на планиметрия и плътна геометрия. НА…… Енциклопедия на Collier

Навигация*

Навигация- отдел за навигация (виж), завършващ презентация на начини за определяне на мястото на кораб в морето с помощта на компас и дневник (виж). Да се ​​определи мястото на кораб в морето означава да се постави на картата точката, в която се намира корабът този моментразположен.… … Енциклопедичен речник F.A. Brockhaus и I.A. Ефрон

COGEN- (Коен) Херман (1842 1918) немски философ, основател и най-ярък представител на Марбургската школа на неокантианството. Основни произведения: „Теория на опита на Кант“ (1885), „Обосновка на етиката на Кант“ (1877), „Оправдание на естетиката на Кант“ (1889), „Логика… ...

Кант Имануел- Жизненият път и писанията на Кант Имануел Кант е роден в Кьонигсберг (сега Калининград) в Източна Прусия през 1724 г. Баща му е сарач, а майка му е домакиня, шест от децата им не доживяват до пълнолетие. Кант винаги е помнил родителите си с ... ... Западната философия от нейния произход до наши дни

КРИТИЧЕСКАТА ФИЛОСОФИЯ НА КАНТ: УЧЕНИЕТО ЗА СПОСОБНОСТИТЕ- (La philosophie critique de Kant: Doctrines des facultes, 1963) от Дельоз. Описвайки трансценденталния метод във въведението, Дельоз отбелязва, че Кант разбира философията като наука за връзката на всяко познание с основните цели... ... История на философията: Енциклопедия

фермен принцип- основният принцип на геометричната оптика (виж Геометрична оптика). Най-простата форма на F. p. е твърдението, че лъч светлина винаги се разпространява в пространството между две точки по пътя, по който времето на неговото преминаване е по-малко от ... Голям съветска енциклопедия

(дескриптивна геометрия)
  • CD (CXDX, C2D2)показва се като точка C5 = D5 A5B5се равнява...
    (дескриптивна геометрия)
  • Определяне на разстоянието между две успоредни равнини
    Определяне на разстоянието между две успоредни равнини в общо положение 01| худобно е да се сведе до проблема за определяне на разстоянието между същите две равнини, трансформирани в положението на проектиращите. В този случай разстоянието между равнините се определя като перпендикуляр между линиите, ...
    (дескриптивна геометрия)
  • Определяне на разстоянието между две пресичащи се прави
    Ако искате да определите най-късото разстояние между две пресичащи се прави, трябва два пъти да промените системите на проекционните равнини. При решаването на този проблем прекият CD (CXDX, C2D2)показва се като точка C5 = D5(фиг. 198). Разстояние от тази точка до проекцията A5B5се равнява...
    (дескриптивна геометрия)
  • Ъгъл между две пресичащи се прави
    Това е ъгълът между две пресичащи се прави, които са успоредни на данните. Така тази задача е подобна на предишната. За да го решите, трябва да вземете произволна точка и да начертаете две прави през нея, успоредни на дадените коси линии, и с помощта на проекционната трансформация да определите необходимия ъгъл....
    (Основи на дескриптивната геометрия. Кратък курси колекция от задачи.)
  • Определяне на разстоянието между две успоредни прави
    Проблемът се решава чрез метода на двойна подмяна на проекционните равнини. На последния етап една от проекционните равнини трябва да е перпендикулярна на една от пресичащите се линии. Тогава най-късото разстояние между тях се определя от стойността на отсечката от перпендикуляра към другата наклонена линия (фиг. 199)....
    (дескриптивна геометрия)
  • След като очерта две точки на дъската с тебешир, учителят предлага на младия ученик задача: да начертае най-краткия път между двете точки.

    Ученикът, след като помисли, усърдно начертава криволичеща линия между тях.

    - Това е най-краткият път! - изненада се учителят. - Кой те научи на това?

    - Баща ми. Той е шофьор на такси.

    Рисунката на наивен ученик е, разбира се, анекдотична, но няма ли да се усмихнете, ако ви кажат, че пунктираната дъга на фиг. 1 е най-краткият път от нос Добра надежда до южния край на Австралия!

    Още по-поразително е следното твърдение: изобразено на фиг. 2 двупосочно пътуване от Япония до Панамския канал е по-кратко от правата линия, начертана между тях на същата карта!

    Ориз. 1. Включено морска картанай-краткият път от нос Добра надежда до южния край на Австралия не е обозначен с права линия ("локсодрома"), а с крива ("ортодрома")


    Всичко това изглежда като шега, но междувременно пред вас са безспорни истини, добре познати на картографите.




    Ориз. 2. Изглежда невероятно, че кривата пътека, свързваща Йокохама на морската карта с Панамския канал, е по-къса от права линия, начертана между същите точки


    За да изясним въпроса, ще трябва да кажем няколко думи за картите като цяло и за морските карти в частност. Изобразяването на части от земната повърхност на хартия не е лесна задача дори по принцип, тъй като Земята е сфера и е известно, че никоя част от сферичната повърхност не може да бъде разположена на равнина без гънки и счупвания. Неволно човек трябва да се примири с неизбежните изкривявания на картите. Измислени са много начини за рисуване на карти, но не всички карти са лишени от недостатъци: някои имат изкривявания от един вид, други от различен вид, но няма карти без изкривявания изобщо.

    Моряците използват карти, съставени по метода на стар холандски картограф и математик от 16 век. Меркатор. Този метод се нарича проекция на Меркатор. Лесно е да разпознаете морска карта по нейната правоъгълна мрежа: меридианите са показани на нея като поредица от успоредни прави линии; кръгове на ширината - също в прави линии, перпендикулярни на първия (виж фиг. 5).

    Представете си сега, че искате да намерите най-краткия път от едно океанско пристанище до друго на същия паралел. В океана има всички пътеки и винаги е възможно да пътувате там по най-краткия път, ако знаете как се намира. В нашия случай е естествено да мислим, че най-краткият път минава по паралела, на който лежат и двете пристанища: все пак на картата това е права линия, а какво може да бъде по-кратко от права пътека! Но грешим: пътят по паралела съвсем не е най-краткият.

    Наистина: на повърхността на една сфера най-късото разстояние между две точки е дъгата на голямата окръжност, която ги свързва. Но кръгът на паралела малък кръг. Дъгата на голям кръг е по-малко извита от дъгата на всеки малък кръг, начертан през същите две точки: по-големият радиус съответства на по-малката кривина. Издърпайте конеца на земното кълбо между нашите две точки (вж. Фиг. 3); ще се уверите, че изобщо не лежи по паралела. Стегната нишка - безспорен показател най-краткия път, и ако не съвпада с паралела на земното кълбо, тогава на морската карта най-краткият път не е обозначен с права линия: припомнете си, че кръговете на паралелите са изобразени на такава карта с прави линии, всяка линия, която не съвпадат с права линия е крива .



    Ориз. 3. Лесен начин да намерите наистина най-краткия път между две точки: трябва да издърпате конец на земното кълбо между тези точки


    След казаното става ясно защо най-краткият път на морската карта е изобразен не като права, а като крива линия.

    Казват, че при избора на посока за Николаевская (сега Октябрская) железопътна линияимаше безкрайни спорове по какъв начин да го положат. Споровете бяха прекратени с намесата на цар Николай I, който реши проблема буквално „директно“: той свърза Санкт Петербург с Москва по линията. Ако това беше направено на карта на Меркатор, щеше да бъде неприятна изненада: вместо права линия, пътят щеше да се окаже крива.

    Всеки, който не избягва изчисленията, може да се убеди чрез просто изчисление, че пътят, който ни изглежда извит на картата, всъщност е по-къс от този, който сме готови да считаме за прав. Нека нашите две пристанища лежат на 60-ия паралел и са разделени на разстояние 60°. (Дали такива две пристанища действително съществуват е, разбира се, без значение за изчисляване.)



    Ориз. 4. Към изчисляването на разстоянията между точките А и В на топката по дъгата на паралела и по дъгата на големия кръг


    На фиг. 4 точка О-център Глобусът, AB -дъгата на окръжността на географската ширина, върху която лежат пристанищата А и Б; внейните 60°. Центърът на кръга на ширината е в точка ОТПредставете си това от центъра Она земното кълбо е начертана през същите пристанища голяма дъга от кръг: неговият радиус OB = OA = R;тя ще премине близо до начертаната дъга AB,но не съвпада.

    Нека изчислим дължината на всяка дъга. Тъй като точките НОи ATлежат на ширина 60°, а след това радиусите ОАи OVпомирявам се с операционна система(оста на земното кълбо) ъгъл 30°. В правоъгълен триъгълник ASOкрак AC (=r),лежащ срещу ъгъл от 30° е равен на половината от хипотенузата АД;

    означава, r=R/2Дължината на дъгата ABе една шеста от дължината на кръга на географската ширина и тъй като този кръг има половината от дължината на големия кръг (съответстващ на половината от радиуса), тогава дължината на дъгата на малкия кръг



    За да определим сега дължината на дъгата на голяма окръжност, начертана между едни и същи точки (т.е. най-късия път между тях), трябва да знаем големината на ъгъла AOW.Акорд КАТО, изваждане на дъгата до 60 ° (малък кръг), е страната на правилен шестоъгълник, вписан в същия малък кръг; Ето защо AB \u003d r \u003d R / 2

    Начертаване на права линия от,свързващ център Оглобусът със средата дакорди AB,получи правоъгълен триъгълник ОПР,къде е ъгълът Д-прав:

    DA= 1/2 AB и OA=R.

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

    От тук намираме (според таблиците):

    =14°28",5

    и следователно

    = 28°57".

    Сега не е трудно да намерите желаната дължина на най-краткия път в километри. Изчислението може да бъде опростено, ако си спомним, че дължината на минута от голям кръг на земното кълбо е

    Научаваме, че пътят по кръга на ширината, показан на морската карта с права линия, е 3333 км, а пътят по големия кръг - по кривата на картата - 3213 км, т.е. със 120 км по-къс.

    Въоръжени с конец и глобус под ръка, можете лесно да проверите правилността на нашите чертежи и да се уверите, че дъгите на големите кръгове наистина лежат, както е показано на чертежите. Показано на фиг. 1 сякаш "правият" морски път от Африка до Австралия е 6020 мили, а "кривият" - ​​5450 мили, т.е. по-къс с 570 мили, или 1050 км. „Директният“ въздушен маршрут на морската карта от Лондон до Шанхай пресича Каспийско море, докато наистина най-краткият маршрут е на север от Санкт Петербург. Ясно е каква роля играят тези въпроси за спестяването на време и гориво.

    Ако в ерата на ветроходното корабоплаване времето не винаги е било ценено - тогава "времето" все още не се е считало за "пари", тогава с появата на парни кораби човек трябва да плаща за всеки допълнителен тон консумирани въглища. Ето защо в наши дни корабите се движат по наистина най-краткия път, често използвайки карти, направени не в Меркатор, а в така наречената "централна" проекция: на тези карти дъгите на големи кръгове са изобразени като прави линии.

    Защо тогава бившите навигатори са използвали такива измамни карти и са избирали неблагоприятни пътища? Грешка е да се мисли, че в старите времена не са знаели за посочената сега характеристика на морските карти. Въпросът се обяснява, разбира се, не с това, а с факта, че картите, съставени по метода на Меркатор, наред с неудобствата, носят много ценни ползи за моряците. Такава карта, първо, изобразява отделни малки части от земната повърхност без изкривяване, запазвайки ъглите на контура. Това не противоречи на факта, че с отдалечаване от екватора всички контури са забележимо разтегнати. На високи географски ширини участъкът е толкова значителен, че морска карта вдъхновява човек, който не е запознат с характеристиките му, с напълно погрешна представа за истинския размер на континентите: Гренландия изглежда е със същия размер като Африка, Аляска е по-голяма от Австралия, въпреки че Гренландия е 15 пъти по-малка от Африка, а Аляска заедно с Гренландия наполовина на Австралия. Но моряк, който е добре запознат с тези характеристики на картата, не може да бъде подведен от тях. Той ги търпи, още повече, че на малки площи морската карта дава точно подобие на природата (фиг. 5).

    От друга страна, морската карта значително улеснява решаването на задачите на навигационната практика. Това е единственият вид карти, на които пътят на кораб с постоянен курс е изобразен като права линия. Да следваш „постоянен курс“ означава да спазваш неизменно една посока, един определен „румб“, с други думи, да вървиш така, че да пресичаш всички меридиани под еднакъв ъгъл. Но този път ("локсодром") може да бъде изобразен като права линия само на карта, на която всички меридиани са прави линии, успоредни една на друга. И тъй като на земното кълбо кръговете на ширината се пресичат с меридианите под прав ъгъл, тогава на такава карта кръговете на ширината трябва да са прави линии, перпендикулярни на линиите на меридианите. Накратко, стигаме точно до координатната мрежа, която представлява характерна черта на морската карта.




    Ориз. 5. Морска или Меркаторска карта на земното кълбо. На такива карти размерите на контурите далеч от екватора са силно преувеличени. Кое например е по-голямо: Гренландия или Австралия? (отговор в текст)


    Пристрастието на моряците към картите на Меркатор вече е разбираемо. В желанието си да определи курса, който да следва, когато отива към определеното пристанище, навигаторът прилага линийка към крайните точки на пътя и измерва ъгъла, който тя сключва с меридианите. Поддържайки през цялото време в открито море в тази посока, навигаторът точно ще доведе кораба до целта. Виждате, че "локсодрумът" е, макар и не най-краткият и не най-икономичният, но в известно отношение много удобен път за един моряк. За да достигнете, например, от нос Добра надежда до южния край на Австралия (вижте фиг. 1), човек трябва винаги да поддържа същия курс S 87 °.50 ". Междувременно, за да доведете кораба до същото крайна точка най-краткия път(според "ортодромията") е необходимо, както се вижда от фигурата, непрекъснато да се променя курсът на плавателния съд: да се започне от курса S 42 °.50 "и да се завърши с курса N 53 °.50 “ (в този случай най-краткият път дори не е осъществим – той опира в ледената стена на Антарктика).

    И двата пътя - по "локсодрома" и по "ортодромата" - съвпадат само когато пътят по големия кръг е изобразен на морската карта като права линия: при движение по екватора или по меридиана. Във всички останали случаи тези пътища са различни.

    Алгоритъмът на Дейкстра е графичен алгоритъм, изобретен от холандския учен Едсгер Дейкстра през 1959 г. Намира най-кратките пътища от един от върховете на графа до всички останали. Алгоритъмът работи само за графи без ребра с отрицателно тегло.

    Помислете за изпълнението на алгоритъма на примера на графиката, показана на фигурата.

    Нека се изисква да се намерят най-късите разстояния от 1-ви връх до всички останали.

    Кръговете показват върховете, линиите показват пътищата между тях (ръбовете на графиката). Номерата на върховете са посочени в кръговете, тяхната "цена" - дължината на пътя - е посочена над краищата. До всеки връх е отбелязан червен етикет - дължината на най-късия път до този връх от връх 1.

    Първа стъпка. Помислете за стъпка в алгоритъма на Дейкстра за нашия пример. Минимален етикет има връх 1. Върхове 2, 3 и 6 са негови съседи.

    Първият съсед на връх 1 от своя страна е връх 2, тъй като дължината на пътя до него е минимална. Дължината на пътя до него през връх 1 е равна на сумата от стойността на етикета на връх 1 и дължината на ръба, преминаващ от 1-ви до 2-ри, т.е. 0 + 7 = 7. Това е по-малко от текущият етикет на връх 2, безкрайност, така че новият етикет на 2-ри връх е 7.

    Извършваме подобна операция с други двама съседи на 1-ви връх - 3-ти и 6-ти.

    Всички съседи на възел 1 са проверени. Текущото минимално разстояние до връх 1 се счита за окончателно и не подлежи на преразглеждане (фактът, че това наистина е така, беше доказан за първи път от Е. Дейкстра). Зачертайте го от графиката, за да отбележите, че този връх е бил посетен.

    Втора стъпка. Стъпката на алгоритъма се повтаря. Отново намираме „най-близкия“ от непосетените върхове. Това е връх 2, обозначен със 7.

    Отново се опитваме да намалим етикетите на съседите на избрания връх, опитвайки се да преминем през тях през 2-рия връх. Съседите на връх 2 са върхове 1, 3 и 4.

    Първият (по ред) съсед на връх 2 е връх 1. Но той вече е бил посетен, така че не правим нищо с 1-ви връх.

    Следващият съсед на връх 2 е връх 3, тъй като има минималния етикет на върховете, отбелязани като непосетени. Ако отидете до него през 2, тогава дължината на такъв път ще бъде равна на 17 (7 + 10 = 17). Но текущият етикет на третия връх е 9, което е по-малко от 17, така че етикетът не се променя.

    Друг съсед на връх 2 е връх 4. Ако отидете до него през 2-ри, тогава дължината на такъв път ще бъде равна на сумата от най-късото разстояние до 2-ри връх и разстоянието между върхове 2 и 4, т.е. , 22 (7 + 15 = 22) . От 22<, устанавливаем метку вершины 4 равной 22.

    Всички съседи на връх 2 са прегледани, замразяваме разстоянието до него и го маркираме като посетен.

    Трета стъпка. Повтаряме стъпката от алгоритъма, като избираме връх 3. След неговата „обработка“ получаваме следните резултати:

    Следващи стъпки. Повтаряме стъпката от алгоритъма за останалите върхове. Това ще бъдат съответно върхове 6, 4 и 5.

    Завършване на изпълнението на алгоритъма. Алгоритъмът прекратява, когато повече върхове не могат да бъдат обработени. В този пример всички върхове са зачеркнати, но е грешка да се приеме, че това ще бъде случаят във всеки пример - някои върхове може да останат незачертани, ако не могат да бъдат достигнати, т.е. ако графиката е прекъсната. Резултатът от алгоритъма е видим на последната фигура: най-краткият път от връх 1 до 2 е 7, до 3 е 9, до 4 е 20, до 5 е 20, до 6 е 11.

    Реализация на алгоритъма на различни езици за програмиране:

    C++

    #include "stdafx.h" #include използване на пространство от имена std; const int V=6; // Алгоритъмът на Дейкстра void Dijkstra(int GR[V][V], int st) ( int distance[V], count, index, i, u, m=st+1; bool visited[V]; for (i= 0 i "< "<> "; cin>>start; Dijkstra(GR, start-1); system("pause>>void"); )

    Паскал

    програма DijkstraAlgorithm; usescrt; constV=6; inf=100000; тип вектор=масив от цели числа; var start: integer; const GR: масив от цели числа=((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)); (алгоритъм на Дейкстра) процедура Dijkstra(GR: масив от цяло число; st: цяло число); променлив брой, индекс, i, u, m, min: цяло число; разстояние: вектор; посетено: масив от булеви; beginm:=st; за i:=1 до V направете начало distance[i]:=inf; посетено[i]:=false; край; разстояние:=0; за count:=1 до V-1 направете start min:=inf; за i:=1 до V направете if (not visited[i]) and (distance[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) и (разстояние[u]<>inf) и (разстояние[u]+GR inf тогава writeln(m," > ", i," = ", разстояние[i]) else writeln(m," > ", i," = ", "маршрутът е недостъпен"); край; (основен програмен блок) begin clrscr; write("Начален възел >> "); четене (започване); Дейкстра (GR, начало); край.

    Java

    импортиране на java.io.BufferedReader; импортиране на java.io.IOException; импортиране на java.io.InputStreamReader; импортиране на java.io.PrintWriter; импортиране на java.util.ArrayList; импортиране на java.util.Arrays; импортиране на java.util.StringTokenizer; public class Solution ( private static int INF = Integer.MAX_VALUE / 2; private int n; //брой върхове в диграф private int m; //брой дъги в диграф private ArrayList прил. //списък на съседство частен ArrayList тегло; //тегло на ръба в диграф частен булев използван; //масив за съхраняване на информация за преминати и непреминали пикове private int dist; //масив за съхраняване на разстоянието от началния връх //масив от предшественици, необходими за възстановяване на най-краткия път от началния връх private int pred; int начало; //начален връх, от който се търси разстоянието до всички останали private BufferedReader cin; частен PrintWriter cout; частен токенизатор на StringTokenizer; //процедура за стартиране на алгоритъма на Дейкстра от началния връх private void dejkstra(int s) ( dist[s] = 0; //най-късото разстояние до началния връх е 0 за (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(); ) //инициализиране на списъка, който съхранява теглата на ръбовете weight = new ArrayList[n]; за (int i = 0; i< n; ++i) { weight[i] = new ArrayList(); ) //прочетете графиката, дадена от списъка с ребра за (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(); } }

    Друг вариант:

    Импортиране на java.io.*; импортиране на java.util.*; публичен клас Dijkstra (частен статичен финал Graph.Edge GRAPH = ( нов Graph.Edge("a", "b", 7), нов Graph.Edge("a", "c", 9), нов Graph.Edge( "a", "f", 14), нов Graph.Edge("b", "c", 10), нов Graph.Edge("b", "d", 15), нов Graph.Edge("c" ", "d", 11), нов Graph.Edge("c", "f", 2), нов Graph.Edge("d", "e", 6), нов Graph.Edge("e", "f", 9), ); private static final String START = "a"; private static final String END = "e"; public static void main(String args) ( Graph g = new Graph(GRAPH); g.dijkstra (START); g.printPath(END); //g.printAllPaths(); ) ) class Graph ( частна финална карта графика; // съпоставяне на имена на върхове към обекти на върхове, изградени от набор от ребра /** Един ръб на графиката (използван само от конструктора на Graph) */ публичен статичен клас 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; ) ) /** Един връх на графиката, пълен с преобразувания към съседни върхове */ публичен статичен клас Vertex внедрява Comparable ( public final String name; public int dist = Integer.MAX_VALUE; // MAX_VALUE се приема за безкрайност public Vertex previous = null; public final Map съседи = нова HashMap<>(); public Vertex(Име на низ) ( this.name = име; ) private void printPath() ( if (this == this.previous) ( System.out.printf("%s", this.name); ) else if ( this.previous == null) ( System.out.printf("%s(unreached)", 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); ) ) /** Изгражда графика от набор от ръбове * / public Graph(Edge edges) ( graph = new HashMap<>(ръбове.дължина); //едно преминаване за намиране на всички върхове за (Edge e: edges) ( if (!graph.containsKey(e.v1)) graph.put(e.v1, new Vertex(e.v1)); if (!graph. containsKey(e.v2)) graph.put(e.v2, new Vertex(e.v2)); ) //друго преминаване за задаване на съседни върхове за (Edge e: edges) ( graph.get(e.v1). neighbours.put(graph.get(e.v2), e.dist); //graph.get(e.v2).neighbours.put(graph.get(e.v1), e.dist); // също направете това за ненасочена графа ) ) /** Изпълнява dijkstra, използвайки определен изходен връх */ public void dijkstra(String startName) ( if (!graph.containsKey(startName)) ( System.err.printf("Graph doesn't съдържа начален връх \"%s\"\n", startName); return; ) final Vertex source = graph.get(startName); NavigableSet q = нов TreeSet<>(); // настройване на върхове за (Vertex v: graph.values()) ( v.previous = v == източник ? източник: нула; v.dist = v == източник ? 0: Integer.MAX_VALUE; q.add( v); ) dijkstra(q); ) /** Реализиране на алгоритъма на dijkstra с помощта на двоична купчина. */ private void dijkstra(final NavigableSet q) ( Vertex u, v; while (!q.isEmpty()) ( u = q.pollFirst(); // връх с най-късо разстояние (първата итерация ще върне източника) if (u.dist == Integer.MAX_VALUE) прекъсване; // можем да игнорираме u (и всички останали върхове), тъй като те са недостижими // разглеждаме разстоянията до всеки съсед за (Map.Entry a: u.neighbours.entrySet()) ( v = a.getKey(); //съседът в тази итерация 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(); } } }

    ° С

    #включи #включи #включи //#define BIG_EXAMPLE typedef struct node_t node_t, *heap_t; typedef struct edge_t edge_t; struct edge_t ( node_t *nd; /* цел на този край */ edge_t *sibling;/* за единично свързан списък */ int len; /* цена на край */); struct node_t ( edge_t *edge; /* единично свързан списък от ръбове */ node_t *via; /* където предишният възел е в най-краткия път */ double dist; /* разстояние от първоначалния възел */ char име; /* the, er , име */ int heap_idx; /* връзка към позиция на куп за актуализиране на разстоянието */); /* --- управление на граници --- */ #ifdef BIG_EXAMPLE # дефиниране на BLOCK_SIZE (1024 * 32 - 1) #else # дефиниране на BLOCK_SIZE 15 #endif edge_t *edge_root = 0, *e_next = 0; /* Не обръщайте внимание на нещата с управлението на паметта, те не са от значение. ) ( 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 = d; e_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); ) ) /* --- неща с приоритетна опашка --- */ heap_t *heap; int heap_len; void set_dist(node_t *nd, node_t *via, double d) ( int i, j; /* вече знаеше по-добър път */ if (nd->via && d >= nd->dist) return; /* намиране на съществуващ запис в купчина или създаване на нов */ nd->dist = d; nd->via = via; i = nd->heap_idx; if (!i) i = ++heap_len; /* upheap */ за (; i > 1 && nd->dist< heap->dist; i = j) (куп [i] = куп [j])-> heap_idx = i; куп [i] = nd; nd->heap_idx = i; ) node_t * pop_queue() ( node_t *nd, *tmp; int i, j; if (!heap_len) return 0; /* премахнете водещия елемент, издърпайте опашния елемент там и downheap */ nd = heap; tmp = heap; for (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; (куп [i] = куп [j])-> heap_idx = i; ) куп [i] = tmp; tmp->heap_idx = i; връщане nd; ) /* --- неща на Dijkstra; недостижими възли никога няма да направят вопашка --- */ 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; # дефинирайте N_NODES ("f" - "a" + 1) node_t * възли = calloc(sizeof(node_t), N_NODES); за (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

    $edge, "cost" => $edge); $neighbours[$edge] = array("end" => $edge, "cost" => $edge); ) $vertices = array_unique($vertices); foreach ($vertices като $vertex) ( $dist[$vertex] = INF; $previous[$vertex] = NULL; ) $dist[$source] = 0; $Q = $върхове; while (count($Q) > 0) ( // TODO - Намерете по-бърз начин за получаване на минимум $min = INF; foreach ($Q като $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

    от колекции импортирайте namedtuple, опашка от pprint импортирайте pprint като pp inf = float("inf") Edge = namedtuple("Edge", "start, end, cost") клас Graph(): def __init__(self, edges): self .edges = edges2 = self.vertices = set(sum(( for e in edges2), )) def dijkstra(self, source, dest): assert source in self.vertices dist = (vertex: inf за връх в self.vertices ) предишен = (връх: Няма за връх в self.vertices) dist = 0 q = self.vertices.copy() съседи = (върх: set() за връх в self.vertices) за начало, край, цена в self. edges: neighbors.add((end, cost)) #pp(neighbours) while q: u = min(q, key=lambda vertex: dist) q.remove(u) if dist[u] == inf or u = = dest: прекъсване за v, цена в съседи[u]: alt = dist[u] + цена, ако 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"]