• Jarak terpendek antara dua titik. Tahukah Anda mengapa lebih jauh dalam garis lurus daripada di busur? Menentukan jarak antara dua garis yang berpotongan

    01.02.2022

    Setelah menguraikan dua titik di papan tulis dengan kapur, guru menawarkan tugas kepada siswa muda: menggambar jalur terpendek antara kedua titik.

    Siswa itu, setelah berpikir, dengan rajin menarik garis yang berliku-liku di antara mereka.

    - Itu cara terpendek! guru terkejut. - Siapa yang mengajarimu itu?

    - Ayahku. Dia adalah seorang sopir taksi.

    Gambar anak sekolah yang naif, tentu saja, bersifat anekdot, tetapi tidakkah Anda akan tersenyum jika diberi tahu bahwa busur putus-putus pada gambar. 1 adalah jalan terpendek dari Tanjung Harapan ke ujung selatan Australia!

    Bahkan lebih mencolok adalah pernyataan berikut: digambarkan pada Gambar. 2 perjalanan pulang pergi dari Jepang ke Terusan Panama lebih pendek dari garis lurus yang ditarik di antara mereka di peta yang sama!

    Beras. 1. Pada peta laut, rute terpendek dari Tanjung Harapan ke ujung selatan Australia tidak ditunjukkan oleh garis lurus ("lokosdrom"), tetapi oleh kurva ("ortodrom")


    Semua ini terlihat seperti lelucon, tetapi sementara itu di depan Anda adalah kebenaran yang tak terbantahkan, yang diketahui oleh para kartografer.




    Beras. 2. Tampaknya luar biasa bahwa jalur lengkung yang menghubungkan Yokohama di peta laut dengan Terusan Panama lebih pendek daripada garis lurus yang ditarik di antara titik-titik yang sama


    Untuk memperjelas masalah ini, beberapa kata harus dikatakan tentang bagan secara umum dan tentang bagan bahari pada khususnya. Menggambarkan bagian-bagian permukaan bumi di atas kertas bukanlah tugas yang mudah, bahkan pada prinsipnya, karena Bumi adalah bola, dan diketahui bahwa tidak ada bagian dari permukaan bola yang dapat ditempatkan di pesawat tanpa lipatan dan patah. Tanpa sadar, seseorang harus bertahan dengan distorsi yang tak terhindarkan pada peta. Banyak cara menggambar peta telah ditemukan, tetapi semua peta tidak bebas dari kekurangan: beberapa memiliki distorsi satu jenis, yang lain dari jenis yang berbeda, tetapi tidak ada peta tanpa distorsi sama sekali.

    Pelaut menggunakan peta yang digambar menurut metode kartografer dan matematikawan Belanda kuno abad ke-16. Mercator. Metode ini disebut proyeksi Mercator. Sangat mudah untuk mengenali peta laut dengan kotak persegi panjangnya: meridian ditampilkan di atasnya sebagai serangkaian garis lurus paralel; lingkaran lintang - juga dalam garis lurus yang tegak lurus dengan yang pertama (lihat Gambar 5).

    Bayangkan sekarang Anda ingin menemukan jalur terpendek dari satu pelabuhan laut ke pelabuhan laut lainnya pada paralel yang sama. Di lautan, semua jalur tersedia, dan selalu memungkinkan untuk melakukan perjalanan ke sana sepanjang jalur terpendek jika Anda tahu bagaimana letaknya. Dalam kasus kami, wajar untuk berpikir bahwa jalur terpendek berjalan di sepanjang paralel di mana kedua port terletak: setelah semua, di peta itu adalah garis lurus, dan apa yang bisa lebih pendek dari jalur lurus! Tapi kita salah: jalan di sepanjang paralel sama sekali bukan yang terpendek.

    Memang: di permukaan bola, jarak terpendek antara dua titik adalah busur lingkaran besar yang menghubungkannya. Tapi lingkaran paralel kecil sebuah lingkaran. Busur lingkaran besar kurang melengkung daripada busur lingkaran kecil mana pun yang ditarik melalui dua titik yang sama: jari-jari yang lebih besar sesuai dengan kelengkungan yang lebih kecil. Tarik benang pada globe di antara dua titik kita (lih. Gbr. 3); Anda akan memastikan bahwa itu tidak terletak sejajar sama sekali. Benang yang diregangkan adalah indikator yang tak terbantahkan dari jalur terpendek, dan jika tidak bertepatan dengan paralel pada bola dunia, maka pada peta laut jalur terpendek tidak ditunjukkan oleh garis lurus: ingat bahwa lingkaran paralel digambarkan seperti itu peta dengan garis lurus, setiap garis yang tidak bertepatan dengan garis lurus , ada melengkung .



    Beras. 3. Cara sederhana untuk menemukan jalur terpendek antara dua titik: Anda perlu menarik utas di globe di antara titik-titik ini


    Setelah apa yang telah dikatakan, menjadi jelas mengapa jalur terpendek pada peta laut digambarkan bukan sebagai garis lurus, tetapi sebagai garis lengkung.

    Mereka mengatakan itu ketika memilih arah untuk Nikolaevskaya (sekarang Oktyabrskaya) kereta api ada perselisihan tanpa akhir tentang cara meletakkannya. Perselisihan diakhiri oleh intervensi Tsar Nicholas I, yang memecahkan masalah secara harfiah "langsung": ia menghubungkan Sankt Peterburg dengan Moskow di sepanjang garis. Jika ini dilakukan di peta Mercator, itu akan menjadi kejutan yang memalukan: alih-alih garis lurus, jalan akan berubah menjadi kurva.

    Siapa pun yang tidak menghindari perhitungan dapat diyakinkan dengan perhitungan sederhana bahwa jalan yang menurut kita melengkung di peta sebenarnya lebih pendek daripada yang kita anggap lurus. Biarkan kedua pelabuhan kita terletak pada paralel ke-60 dan dipisahkan oleh jarak 60°. (Apakah dua pelabuhan seperti itu benar-benar ada, tentu saja tidak penting untuk perhitungan.)



    Beras. 4. Untuk perhitungan jarak antara titik A dan B pada bola sepanjang busur garis sejajar dan sepanjang busur lingkaran besar


    pada gambar. 4 poin O - pusat dunia, AB - busur lingkaran garis lintang tempat pelabuhan terletak A dan B; di dia 60 °. Pusat lingkaran garis lintang berada di suatu titik DARI Bayangkan itu dari pusat HAI bola dunia ditarik melalui pelabuhan yang sama busur lingkaran besar: jari-jarinya OB = OA = R; itu akan melewati dekat dengan busur yang ditarik AB, tapi itu tidak cocok.

    Mari kita hitung panjang setiap busur. Sejak poin TETAPI dan PADA terletak pada garis lintang 60°, maka jari-jari OA dan OV berdandan dengan OS(sumbu bola dunia) membentuk sudut 30°. Dalam segitiga siku-siku ASO kaki AC (=r), terletak di depan sudut 30° sama dengan setengah sisi miring JSC;

    cara, r=R/2 Panjang busur AB adalah seperenam panjang lingkaran garis lintang, dan karena lingkaran ini memiliki setengah panjang lingkaran besar (sesuai dengan setengah jari-jari), maka panjang busur lingkaran kecil



    Untuk menentukan sekarang panjang busur lingkaran besar yang ditarik antara titik yang sama (yaitu, jalur terpendek di antara mereka), kita perlu mengetahui besar sudut AW. akord SEBAGAI, mengurangi busur menjadi 60 ° (lingkaran kecil), adalah sisi segi enam biasa yang tertulis dalam lingkaran kecil yang sama; itu sebabnya AB \u003d r \u003d R / 2

    Menggambar garis lurus od, pusat penghubung HAI globe dengan bagian tengah D akord AB, dapatkan segitiga siku-siku ODA, dimana sudut D- lurus:

    DA= 1/2 AB dan OA=R.

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

    Dari sini kami menemukan (menurut tabel):

    =14°28",5

    dan karenanya

    = 28°57".

    Sekarang tidak sulit untuk menemukan panjang jalur terpendek yang diinginkan dalam kilometer. Perhitungannya dapat disederhanakan jika kita ingat bahwa panjang satu menit lingkaran besar dunia adalah

    Kita mengetahui bahwa jalur di sepanjang lingkaran garis lintang, yang ditunjukkan pada peta laut dengan garis lurus, adalah 3333 km, dan jalur di sepanjang lingkaran besar - sepanjang kurva di peta - 3213 km, yaitu 120 km lebih pendek.

    Berbekal benang dan bola dunia, Anda dapat dengan mudah memeriksa kebenaran gambar kami dan memastikan bahwa busur lingkaran besar benar-benar terletak seperti yang ditunjukkan pada gambar. Ditampilkan pada gambar. 1 seolah-olah rute laut "lurus" dari Afrika ke Australia adalah 6020 mil, dan "kurva" - 5450 mil, yaitu lebih pendek 570 mil, atau 1050 km. Rute udara "langsung" pada peta laut dari London ke Shanghai memotong melalui Laut Kaspia, sedangkan rute terpendek terletak di utara St. Petersburg. Jelas peran apa yang dimainkan masalah ini dalam menghemat waktu dan bahan bakar.

    Jika di era pelayaran pelayaran waktu tidak selalu dihargai - maka "waktu" belum dianggap "uang", maka dengan munculnya kapal uap, seseorang harus membayar untuk setiap ton tambahan batubara yang dikonsumsi. Itulah sebabnya di zaman kita kapal-kapal menavigasi di sepanjang jalur terpendek, sering kali menggunakan peta yang dibuat bukan di Mercator, tetapi dalam apa yang disebut proyeksi "pusat": pada peta-peta ini, busur lingkaran besar digambarkan sebagai garis lurus.

    Lalu, mengapa mantan navigator menggunakan peta yang menipu seperti itu dan memilih jalur yang tidak menguntungkan? Adalah suatu kesalahan untuk berpikir bahwa di masa lalu mereka tidak tahu tentang fitur grafik laut yang sekarang ditunjukkan. Masalahnya dijelaskan, tentu saja, bukan dengan ini, tetapi oleh fakta bahwa bagan yang digambar menurut metode Mercator, bersama dengan ketidaknyamanan, memiliki manfaat yang sangat berharga bagi para pelaut. Peta semacam itu, pertama, menggambarkan bagian-bagian kecil yang terpisah dari permukaan bumi tanpa distorsi, menjaga sudut-sudut kontur. Ini tidak bertentangan dengan fakta bahwa dengan jarak dari khatulistiwa, semua kontur terentang secara nyata. Di garis lintang tinggi, bentangannya begitu signifikan sehingga bagan laut menginspirasi seseorang yang tidak terbiasa dengan fitur-fiturnya dengan gagasan yang sama sekali salah tentang ukuran sebenarnya dari benua: Greenland tampaknya memiliki ukuran yang sama dengan Afrika, Alaska lebih besar dari Australia, meskipun Greenland 15 kali lebih kecil dari Afrika, dan Alaska bersama dengan Greenland setengah ukuran Australia. Tetapi seorang pelaut yang sangat mengenal ciri-ciri peta ini tidak dapat disesatkan oleh mereka. Dia tahan dengan mereka, terutama karena, dalam area kecil, peta laut memberikan kemiripan yang tepat dari alam (Gbr. 5).

    Di sisi lain, peta laut sangat memudahkan penyelesaian tugas-tugas latihan navigasi. Dia - genus tunggal peta di mana jalur kapal di jalur konstan digambarkan sebagai garis lurus. Mengikuti "jalan yang konstan" berarti menjaga selalu satu arah, satu "rhumb" yang pasti, dengan kata lain, untuk pergi sedemikian rupa untuk melintasi semua meridian pada sudut yang sama. Tapi jalan ini ("loksodrom") dapat digambarkan sebagai garis lurus hanya pada peta di mana semua meridian adalah garis lurus sejajar satu sama lain. Dan karena di dunia lingkaran garis lintang berpotongan dengan meridian di sudut kanan, maka pada peta seperti itu lingkaran garis lintang harus berupa garis lurus yang tegak lurus dengan garis meridian. Singkatnya, kami tiba tepat di grid koordinat yang merupakan fitur karakteristik dari peta laut.




    Beras. 5. Peta dunia bahari atau Mercator. Pada peta seperti itu, dimensi kontur yang jauh dari khatulistiwa sangat dilebih-lebihkan. Mana, misalnya, yang lebih besar: Greenland atau Australia? (jawaban dalam teks)


    Predileksi pelaut untuk peta Mercator sekarang dapat dimengerti. Ingin menentukan jalur yang harus diikuti saat menuju pelabuhan yang ditentukan, navigator menerapkan penggaris ke titik akhir jalur dan mengukur sudut yang dibuatnya dengan meridian. Tetap berada di laut terbuka sepanjang waktu ke arah ini, navigator akan secara akurat membawa kapal ke sasaran. Anda melihat bahwa "loksodrom", meskipun bukan yang terpendek dan bukan yang paling ekonomis, tetapi dalam hal tertentu cara yang sangat nyaman bagi seorang pelaut. Untuk mencapai, misalnya, dari Tanjung Harapan ke ujung selatan Australia (lihat Gambar 1), seseorang harus selalu menjaga haluan yang sama S 87°, 50 ". Sementara itu, untuk membawa kapal ke tempat yang sama titik akhir dengan cara terpendek (sepanjang " "), perlu, seperti dapat dilihat dari gambar, untuk terus mengubah arah kapal: mulai dari jalur S 42 °, 50 "dan diakhiri dengan jalur N 53 °. 50" (dalam hal ini, jalur terpendek bahkan tidak layak - itu terletak di dinding es Antartika ).

    Kedua jalur - di sepanjang "lokosdrom" dan di sepanjang "ortodrom" - hanya bertepatan ketika jalur di sepanjang lingkaran besar digambarkan pada peta laut sebagai garis lurus: ketika bergerak di sepanjang khatulistiwa atau di sepanjang meridian. Dalam semua kasus lain, jalur ini berbeda.

    (Geometri deskriptif)
  • CD (CXDX, C2D2) ditampilkan sebagai titik C5 = D5 A5B5 sama...
    (Geometri deskriptif)
  • Menentukan jarak antara dua bidang sejajar
    Menentukan jarak antara dua bidang sejajar posisi umum 01| X lebih mudah untuk menguranginya menjadi masalah menentukan jarak antara dua bidang yang sama, diubah menjadi posisi yang memproyeksikan. Dalam hal ini, jarak antara bidang didefinisikan sebagai tegak lurus antara garis, ...
    (Geometri deskriptif)
  • Menentukan jarak antara dua garis yang berpotongan
    Jika Anda ingin menentukan jarak terpendek antara dua garis yang berpotongan, Anda harus mengubah sistem bidang proyeksi dua kali. Saat memecahkan masalah ini, langsung CD (CXDX, C2D2) ditampilkan sebagai titik C5 = D5(Gbr. 198). Jarak dari titik ini ke proyeksi A5B5 sama...
    (Geometri deskriptif)
  • Sudut antara dua garis lurus yang berpotongan
    Ini adalah sudut antara dua garis berpotongan yang sejajar dengan data. Jadi, tugas ini mirip dengan yang sebelumnya. Untuk menyelesaikannya, Anda perlu mengambil titik sembarang dan menggambar dua garis melaluinya sejajar dengan garis miring yang diberikan, dan menggunakan transformasi proyeksi untuk menentukan sudut yang diperlukan....
    (Dasar-dasar geometri deskriptif. Kursus singkat dan kumpulan masalah.)
  • Menentukan jarak antara dua garis sejajar
    Masalahnya diselesaikan dengan metode penggantian ganda bidang proyeksi. Pada tahap akhir, salah satu bidang proyeksi harus tegak lurus terhadap salah satu garis yang berpotongan. Kemudian jarak terpendek antara mereka ditentukan oleh nilai segmen tegak lurus terhadap garis miring lainnya (Gbr. 199)....
    (Geometri deskriptif)
  • Jalur sepanjang garis putus-putus pada gambar lebih pendek dari jalur sepanjang garis padat. Dan sekarang sedikit lebih detail tentang contoh rute laut:

    Jika Anda berlayar dalam jalur yang konstan, maka lintasan kapal di permukaan bumi akan menjadi kurva, yang disebut dalam matematika logaritmaspiral.

    Dalam navigasi, garis kelengkungan ganda yang rumit ini disebut loxodromia, yang dalam bahasa Yunani berarti "lari miring".

    Namun, jarak terpendek antara dua titik di dunia diukur sepanjang busur lingkaran besar.

    Busur lingkaran besar diperoleh sebagai jejak dari perpotongan permukaan bumi dengan bidang yang melewati pusat bumi, diambil sebagai bola.

    Dalam navigasi, busur lingkaran besar disebut lingkaran besar, yang berarti "lari lurus". Fitur kedua dari lingkaran besar adalah bahwa ia melintasi meridian di bawah sudut yang berbeda(Gbr. 29).

    Perbedaan jarak antara dua titik di permukaan bumi di sepanjang loxodrome dan orthodrome hanya penting secara praktis untuk penyeberangan laut besar.

    Dalam kondisi normal, perbedaan ini diabaikan dan navigasi dilakukan pada jalur yang konstan, yaitu. oleh loksodrom.

    Untuk menurunkan persamaan, kami mengambil loxodromies (Gbr. 30, sebuah) dua titik TETAPI dan PADA, jarak antara mereka hanya kecil. Menggambar meridian dan paralel melalui mereka, kita mendapatkan segitiga bola siku-siku dasar ABC. Dalam segitiga ini, sudut yang dibentuk oleh perpotongan meridian dan paralel adalah siku-siku, dan sudut PnAB sama dengan arah kapal K. Katet AC mewakili segmen busur meridian dan dapat dinyatakan

    di mana R - radius Bumi diambil sebagai bola;

    - kenaikan dasar garis lintang (perbedaan garis lintang).

    kaki SW mewakili segmen busur paralel

    dimana r - radius paralel;

    Δλ - perbedaan dasar garis bujur.

    Dari segitiga OO 1 C dapat ditemukan bahwa

    Kemudian dalam bentuk terakhir kaki SW dapat diungkapkan seperti ini:

    Dengan asumsi segitiga bola elementer ABC untuk datar, tulis

    Setelah reduksi R dan mengganti kenaikan kecil dasar koordinat dengan yang sangat kecil, kami memiliki

    Kami mengintegrasikan ekspresi yang dihasilkan dalam rentang dari 1, 1 hingga 2, λ 2 mempertimbangkan nilai tgK sebagai nilai konstan:

    Di sisi kanan kita memiliki integral tabular. Setelah mensubstitusi nilainya, kita memperoleh persamaan loxodrome pada bola

    Analisis persamaan ini memungkinkan kita untuk menarik kesimpulan berikut:

    Pada jalur 0 dan 180 °, loxodrome berubah menjadi busur lingkaran besar - meridian;

    Pada jalur 90 dan 270 °, loxodrome bertepatan dengan paralel;

    Loxodrome melintasi setiap paralel hanya sekali, dan setiap meridian tidak terhitung berkali-kali. itu. spiral mendekati kutub, itu tidak mencapai itu.

    Navigasi dalam jalur yang konstan, yaitu, di sepanjang loxodrome, meskipun bukan jarak terpendek antara dua titik di Bumi, mewakili kenyamanan yang cukup besar bagi navigator.

    Persyaratan peta navigasi laut dapat dirumuskan berdasarkan keunggulan navigasi sepanjang loxodrome dan hasil analisis persamaannya sebagai berikut.

    1. Loxodrome, melintasi meridian pada sudut konstan, harus digambarkan sebagai garis lurus.

    2. Proyeksi kartografi yang digunakan untuk pembuatan peta harus sesuai sehingga arah, arah, dan sudut di atasnya sesuai dengan nilainya di lapangan.

    3. Garis meridian dan garis sejajar, seperti garis lintasan 0, 90, 180° dan 270°, harus merupakan garis lurus yang saling tegak lurus.

    Jarak terpendek antara dua titik tertentu di permukaan Bumi, diambil sebagai bola, adalah busur lingkaran besar yang lebih kecil yang melewati titik-titik ini. Kecuali dalam kasus kapal yang mengikuti meridian atau khatulistiwa, lingkaran besar melintasi meridian pada sudut yang berbeda. Oleh karena itu, kapal yang mengikuti kurva seperti itu harus mengubah arahnya sepanjang waktu. Praktis lebih mudah untuk mengikuti jalur yang membuat sudut konstan dengan meridian dan digambarkan pada peta dalam proyeksi Mercator dengan garis lurus - loxodrome. Namun, pada jarak yang jauh, perbedaan panjang ortodrom dan loksodrom mencapai nilai yang signifikan. Oleh karena itu, dalam kasus seperti itu, ortodrom dihitung dan titik perantara ditandai di atasnya, di antaranya mereka berenang di sepanjang loxodrome.

    Proyeksi kartografi yang memenuhi persyaratan di atas diusulkan oleh kartografer Belanda Gerard Cramer (Mercator) pada tahun 1569. Untuk menghormati penciptanya, proyeksi itu dinamai Mercator.

    Dan siapa yang ingin mendapatkan lebih banyak lagi informasi yang menarik Belajarlah lagi Artikel asli ada di website InfoGlaz.rf Tautan ke artikel dari mana salinan ini dibuat -

    JARAK, jarak, lih. 1. Ruang yang memisahkan dua titik, celah antara sesuatu. Jarak terpendek antara dua titik pada garis lurus. Tinggal dari kami pada jarak dua kilometer. "Komandan membiarkan mereka masuk pada jarak terdekat ... Kamus Penjelasan Ushakov

    jarak- kata benda, s., gunakan. sering Morfologi: (tidak) apa? jarak untuk apa? jarak, (lihat) apa? jarak dari? jarak, apa? tentang jarak; hal. apa? jarak, (tidak) apa? jarak, mengapa? jarak, (lihat) apa? jarak dari? jarak... Kamus Dmitriev

    jarak- SAYA; lihat Ruang yang memisahkan dua titik, dua benda, dll., celah antara seseorang, dari l. Sungai terpendek antara dua titik. R.dari rumah ke sekolah. Mundur ke sungai terdekat. Pada jarak satu meter, lengan terentang. Tahu sesuatu, merasakan sesuatu. pada … … kamus ensiklopedis

    jarak- SAYA; lihat Lihat juga jarak a) Ruang yang memisahkan dua titik, dua benda, dll., jarak antara seseorang, dari l. Jarak terpendek antara dua titik. Jarak dari rumah ke sekolah. Mundur ke jarak dekat / nie ... Kamus banyak ekspresi

    GEOMETRI- cabang matematika yang mempelajari sifat-sifat berbagai bentuk (titik, garis, sudut, benda dua dimensi dan tiga dimensi), ukuran dan posisi relatifnya. Untuk kenyamanan mengajar, geometri dibagi menjadi planimetri dan geometri padat. PADA… … Ensiklopedia Collier

    Navigasi*

    Navigasi- departemen navigasi (lihat), menyimpulkan presentasi cara menentukan tempat kapal di laut, menggunakan kompas dan log (lihat). Untuk menentukan tempat kapal di laut berarti menempatkan di peta titik di mana kapal itu berada saat ini. ... ... Kamus Ensiklopedis F.A. Brockhaus dan I.A. Efron

    COGEN- (Cohen) Hermann (1842 1918) Filsuf Jerman, pendiri dan perwakilan paling menonjol dari sekolah neo-Kantianisme Marburg. Karya-karya besar: 'Teori Pengalaman Kant' (1885), 'Pembenaran Etika Kant' (1877), 'Pembenaran Estetika Kant' (1889), 'Logika… ...

    Kant Immanuel - jalan hidup dan tulisan Kant Immanuel Kant lahir di Konigsberg (sekarang Kaliningrad) di Prusia Timur pada tahun 1724. Ayahnya adalah seorang pelana dan ibunya seorang ibu rumah tangga, enam dari anak-anak mereka tidak hidup sampai dewasa. Kant selalu mengingat orang tuanya dengan ... ... Filsafat Barat dari asal-usulnya hingga saat ini

    FILOSOFI KRITIS KANT: DOKTRIN KEMAMPUAN- (La philosophie critique de Kant: Doctrines des facultes, 1963) oleh Deleuze. Menggambarkan metode transendental dalam pendahuluan, Deleuze mencatat Kant memahami filsafat sebagai ilmu tentang hubungan semua pengetahuan dengan tujuan-tujuan esensial... ... Sejarah Filsafat: Ensiklopedia

    prinsip pertanian- prinsip dasar optik geometris (Lihat Optik geometris). Bentuk paling sederhana dari F. p. adalah pernyataan bahwa seberkas cahaya selalu merambat di ruang antara dua titik di sepanjang lintasan yang waktu tempuhnya kurang dari ... Ensiklopedia Besar Soviet

    Algoritma Dijkstra adalah algoritma graf yang ditemukan oleh ilmuwan Belanda Edsger Dijkstra pada tahun 1959. Menemukan jalur terpendek dari salah satu simpul dari grafik ke semua yang lain. Algoritma bekerja hanya untuk graf tanpa sisi berbobot negatif.

    Pertimbangkan eksekusi algoritma pada contoh grafik yang ditunjukkan pada gambar.

    Biarkan diperlukan untuk menemukan jarak terpendek dari simpul pertama ke semua simpul lainnya.

    Lingkaran menunjukkan simpul, garis menunjukkan jalur di antara mereka (tepi grafik). Jumlah simpul ditunjukkan dalam lingkaran, "harga" mereka - panjang jalur - ditunjukkan di atas tepi. Di sebelah setiap simpul, label merah ditandai - panjang jalur terpendek ke simpul ini dari simpul 1.

    Langkah pertama. Pertimbangkan langkah dalam algoritma Dijkstra untuk contoh kita. Simpul 1 memiliki label minimum.Simpul 2, 3, dan 6 adalah tetangganya.

    Tetangga pertama dari simpul 1 pada gilirannya adalah simpul 2, karena panjang lintasannya minimal. Panjang lintasan yang melalui simpul 1 sama dengan jumlah nilai label simpul 1 dan panjang tepi dari 1 ke 2, yaitu 0 + 7 = 7. Ini lebih kecil dari label simpul 2 saat ini, tak terhingga, jadi label baru simpul ke-2 adalah 7.

    Kami melakukan operasi serupa dengan dua tetangga lain dari simpul ke-1 - ke-3 dan ke-6.

    Semua tetangga node 1 diperiksa. Jarak minimum saat ini ke puncak 1 dianggap final dan tidak dapat direvisi (fakta bahwa memang demikian, pertama kali dibuktikan oleh E. Dijkstra). Coretlah dari grafik untuk menandai bahwa simpul ini telah dikunjungi.

    Tahap kedua. Langkah algoritma diulang. Sekali lagi kami menemukan "terdekat" dari simpul yang belum dikunjungi. Ini adalah simpul 2 berlabel 7.

    Sekali lagi kami mencoba mengurangi label tetangga dari simpul yang dipilih, mencoba melewatinya melalui simpul ke-2. Tetangga simpul 2 adalah simpul 1, 3, dan 4.

    Tetangga pertama (berurutan) dari simpul 2 adalah simpul 1. Tapi sudah dikunjungi, jadi kita tidak melakukan apa-apa dengan simpul pertama.

    Tetangga berikutnya dari simpul 2 adalah simpul 3, karena memiliki label minimum dari simpul yang ditandai sebagai belum dikunjungi. Jika Anda melewatinya melalui 2, maka panjang jalan seperti itu akan sama dengan 17 (7 + 10 = 17). Tetapi label saat ini dari simpul ketiga adalah 9, yang kurang dari 17, sehingga labelnya tidak berubah.

    Tetangga lain dari simpul 2 adalah simpul 4. Jika Anda melaluinya melalui simpul ke-2, maka panjang jalur tersebut akan sama dengan jumlah jarak terpendek ke simpul ke-2 dan jarak antara simpul 2 dan 4, yaitu , 22 (7 + 15 = 22) . Sejak 22<, устанавливаем метку вершины 4 равной 22.

    Semua tetangga simpul 2 telah dilihat, kami membekukan jaraknya dan menandainya sebagai dikunjungi.

    Langkah ketiga. Kami mengulangi langkah algoritma dengan memilih simpul 3. Setelah "memproses", kami mendapatkan hasil sebagai berikut:

    Langkah selanjutnya. Kami mengulangi langkah algoritma untuk simpul yang tersisa. Ini akan menjadi simpul 6, 4 dan 5, masing-masing.

    Penyelesaian eksekusi algoritma. Algoritme berakhir ketika tidak ada lagi simpul yang dapat diproses. Dalam contoh ini, semua simpul dicoret, tetapi merupakan kesalahan untuk mengasumsikan bahwa ini akan menjadi kasus dalam contoh apa pun - beberapa simpul mungkin tetap tidak dicoret jika tidak dapat dijangkau, yaitu jika graf terputus. Hasil algoritma terlihat pada gambar terakhir: jalur terpendek dari simpul 1 ke 2 adalah 7, ke 3 adalah 9, ke 4 adalah 20, ke 5 adalah 20, ke 6 adalah 11.

    Implementasi algoritma dalam berbagai bahasa pemrograman:

    C++

    #sertakan "stdafx.h" #sertakan menggunakan namespace std; const int V=6; // Algoritma Dijkstra void Dijkstra(int GR[V][V], int st) ( int jarak[V], hitung, indeks, i, u, m=st+1; bool dikunjungi[V]; for (i= 0 saya "< "<> "; cin>>mulai; Dijkstra(GR, start-1); system("jeda>>batal"); )

    Pascal

    program DijkstraAlgorithm; menggunakancrt; constV=6; inf=100.000; jenis vektor=array bilangan bulat; var mulai: bilangan bulat; const GR: array bilangan bulat=((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)); (algoritma Dijkstra) prosedur Dijkstra(GR: array bilangan bulat; st: bilangan bulat); var count, index, i, u, m, min: integer; jarak vektor; dikunjungi: array boolean; mulai:=st; untuk i:=1 sampai V lakukan start distance[i]:=inf; dikunjungi[i]:=salah; akhir; jarak:=0; untuk count:=1 sampai V-1 lakukan mulai min:=inf; untuk i:=1 hingga V lakukan jika (tidak dikunjungi[i]) dan (jarak[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) dan (jarak[u]<>inf) dan (jarak[u]+GR inf lalu writeln(m," > ", i," = ", distance[i]) else writeln(m," > ", i," = ", "rute tidak tersedia"); akhir; (blok program utama) mulai clrscr; write("Simpul awal >> "); baca (mulai); Dijkstra(GR, mulai); akhir.

    Jawa

    impor java.io.BufferedReader; impor java.io.IOException; impor java.io.InputStreamReader; impor java.io.PrintWriter; impor java.util.ArrayList; impor java.util.Arrays; impor java.util.StringTokenizer; Solusi kelas publik ( private static int INF = Integer.MAX_VALUE / 2; private int n; //jumlah simpul dalam digraph private int m; //jumlah busur dalam digraph private ArrayList adj; //daftar kedekatan private ArrayList bobot; //bobot tepi dalam digraph private boolean yang digunakan; //array untuk menyimpan informasi tentang puncak yang dilewati dan tidak dilewati private int dist; //array untuk menyimpan jarak dari vertex awal //array ancestor yang dibutuhkan untuk mengembalikan jalur terpendek dari vertex awal private int pred; int mulai; // titik awal, dari mana jarak ke semua titik lainnya dicari private BufferedReader cin; cout pribadi PrintWriter; tokenizer StringTokenizer pribadi; //prosedur untuk memulai algoritma Dijkstra dari titik awal private void dejkstra(int s) ( dist[s] = 0; //jarak terpendek ke titik awal adalah 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(); ) //menginisialisasi daftar yang menyimpan bobot dari edge weight = new ArrayList[n]; untuk (int i = 0; i< n; ++i) { weight[i] = new ArrayList(); ) //membaca grafik yang diberikan oleh daftar sisi untuk (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(); } }

    Pilihan lain:

    Impor java.io.*; impor java.util.*; public class Dijkstra ( private static final Graph.Edge GRAPH = ( new Graph.Edge("a", "b", 7), new Graph.Edge("a", "c", 9), new Graph.Edge( "a", "f", 14), Graph.Edge baru("b", "c", 10), Graph.Edge baru("b", "d", 15), Graph.Edge baru("c ", "d", 11), Graph.Edge baru("c", "f", 2), Graph.Edge baru("d", "e", 6), Graph.Edge baru("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 (MULAI); g.printPath(END); //g.printAllPaths(); ) ) class Graph ( private final Map grafik; // pemetaan nama vertex ke objek Vertex, dibangun dari sekumpulan Edge /** Satu edge dari graph (hanya digunakan oleh Graph constructor) */ 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; ) ) /** Satu simpul dari graf, lengkap dengan pemetaan ke simpul tetangga */ kelas statis publik Vertex mengimplementasikan Sebanding ( nama String final publik; public int dist = Integer.MAX_VALUE; // MAX_VALUE diasumsikan tak terhingga publik Vertex sebelumnya = null; Peta final publik tetangga = HashMap baru<>(); 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(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); ) ) /** Membangun grafik dari sekumpulan edge * / Grafik publik (Tepi tepi) ( grafik = HashMap baru<>(tepi.panjang); //satu pass untuk menemukan semua simpul untuk (Edge e: edge) ( if (!graph.containsKey(e.v1)) graph.put(e.v1, new Vertex(e.v1)); if (!graph. berisiKey(e.v2)) graph.put(e.v2, new Vertex(e.v2)); ) //pass lain untuk mengatur simpul tetangga untuk (Edge e: edge) ( graph.get(e.v1). tetangga.put(graph.get(e.v2), e.dist); //graph.get(e.v2).neighbours.put(graph.get(e.v1), e.dist); // juga lakukan ini untuk graf tak berarah ) ) /** Menjalankan dijkstra menggunakan simpul sumber tertentu */ public void dijkstra(String startName) ( if (!graph.containsKey(startName)) ( System.err.printf("Graph tidak berisi start vertex \"%s\"\n", startName); return; ) final Vertex source = graph.get(startName); NavigableSet q = Kumpulan Pohon baru<>(); // set-up vertex untuk (Vertex v: graph.values()) ( v.previous = v == source ? source: null; v.dist = v == source ? 0: Integer.MAX_VALUE; q.add( v); ) dijkstra(q); ) /** Implementasi algoritma dijkstra menggunakan tumpukan biner. */ private void dijkstra(final NavigableSet q) ( Titik u, v; while (!q.isEmpty()) ( u = q.pollFirst(); // titik dengan jarak terpendek (iterasi pertama akan mengembalikan sumber) if (u.dist == Integer.MAX_VALUE) break; // kita dapat mengabaikan u (dan simpul lainnya yang tersisa) karena mereka tidak dapat dijangkau // melihat jarak ke setiap tetangga untuk (Map.Entry a: u.neighbours.entrySet()) ( v = a.getKey(); //tetangga dalam iterasi ini final int alternatifDist = 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

    #termasuk #termasuk #termasuk //#define BIG_EXAMPLE typedef struct node_t node_t, *heap_t; typedef struct edge_t edge_t; struct edge_t ( node_t *nd; /* target dari edge ini */ edge_t *saudara;/* untuk single linked list */ int len; /* edge cost */ ); struct node_t ( edge_t *edge; /* daftar tepi yang ditautkan secara tunggal */ node_t *via; /* di mana node sebelumnya berada di jalur terpendek */ double dist; /* jarak dari node asal */ nama char; /* the, er , nama */ int heap_idx; /* link ke posisi heap untuk memperbarui jarak */ ); /* --- manajemen tepi --- */ #ifdef BIG_EXAMPLE # tentukan BLOCK_SIZE (1024 * 32 - 1) #else # tentukan BLOCK_SIZE 15 #endif edge_t *edge_root = 0, *e_next = 0; /* Jangan pedulikan hal-hal manajemen memori, itu tidak penting. Berpura-pura 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 = 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); ) ) /* --- hal-hal antrian prioritas --- */ heap_t *heap; int heap_len; void set_dist(node_t *nd, node_t *via, double d) ( int i, j; /* sudah tahu jalur yang lebih baik */ if (nd->via && d >= nd->dist) return; /* temukan entri heap yang ada, atau buat entri baru */ nd->dist = d; nd->via = via; i = nd->heap_idx; if (!i) i = ++heap_len; /* upheap */ for (; i > 1 && nd->dist< heap->daerah; i = j) (heap[i] = heap[j])->heap_idx = i; tumpukan[i] = nd; nd->heap_idx = i; ) node_t * pop_queue() ( node_t *nd, *tmp; int i, j; if (!heap_len) return 0; /* hapus elemen utama, tarik elemen ekor ke sana dan turunkan */ 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; (heap[i] = heap[j])->heap_idx = i; ) tumpukan[i] = tmp; tmp->heap_idx = i; kembali dan; ) /* --- Barang Dijkstra; node yang tidak dapat dijangkau tidak akan pernah masuk ke antrian --- */ 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 *nodes = calloc(sizeof(node_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

    $tepi, "biaya" => $tepi); $neighbours[$edge] = array("end" => $edge, "cost" => $edge); ) $simpul = array_unique($simpul); foreach ($vertex sebagai $vertex) ( $dist[$vertex] = INF; $previous[$vertex] = NULL; ) $dist[$source] = 0; $Q = $simpul; while (count($Q) > 0) ( // TODO - Temukan cara lebih cepat untuk mendapatkan minimum $min = INF; foreach ($Q sebagai $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

    dari collections, import namedtuple, queue from pprint import pprint as pp inf = float("inf") Edge = namedtuple("Edge", "start, end, cost") class Graph(): def __init__(self, edge): self .edges = edge2 = self.vertices = set(sum(( untuk e di edge2), )) def dijkstra(self, source, dest): menegaskan sumber di self.vertices dist = (vertex: inf untuk simpul di self.vertices ) sebelumnya = (simpul: Tidak ada untuk simpul di self.vertices) dist = 0 q = self.vertices.copy() tetangga = (vertex: set() untuk simpul di self.vertices) untuk awal, akhir, biaya dalam diri. edge: neighbor.add((end, cost)) #pp(neighbours) while q: u = min(q, key=lambda vertex: dist) q.remove(u) if dist[u] == inf or u = = tujuan: istirahat untuk v, biaya di tetangga[u]: alt = dist[u] + biaya jika 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"]

    Artikel serupa