คุณรู้ไหมว่าทำไมมันจึงเป็นเส้นตรงมากกว่าในส่วนโค้ง? การกำหนดระยะห่างระหว่างเส้นขนานสองเส้น ระยะทางที่สั้นที่สุดระหว่างจุดสองจุดคือเท่าใด

เส้นทางตามเส้นประในภาพจะสั้นกว่าเส้นทางตามเส้นทึบ และตอนนี้รายละเอียดเพิ่มเติมเล็กน้อยโดยใช้ตัวอย่างเส้นทางทะเล:

หากแล่นไปในเส้นทางคงที่แล้ววิถีของเรือจะแล่นไป พื้นผิวโลกจะเป็นเส้นโค้งที่เรียกว่าในวิชาคณิตศาสตร์ ลอการิทึมเกลียว.

ในการเดินเรือ เรียกว่าเส้นที่ซับซ้อนของความโค้งสองเท่า โรโซโดรม, ซึ่งแปลมาจากภาษากรีกแปลว่า "วิ่งเฉียง"

อย่างไรก็ตาม ระยะทางที่สั้นที่สุดระหว่างจุดสองจุดบนโลกนั้นวัดตามส่วนโค้งของวงกลมใหญ่

ส่วนโค้งของวงกลมใหญ่นั้นได้มาจากรอยตัดของพื้นผิวโลกโดยมีระนาบที่ผ่านจุดศูนย์กลางของโลกซึ่งถือเป็นลูกบอล

ในทางการเดินเรือ เรียกว่า ส่วนโค้งวงกลมใหญ่ ออร์โธโดรมี, ซึ่งแปลว่า “วิ่งตรง” คุณลักษณะที่สองของ orthodromy คือมันตัดเส้นเมอริเดียนในมุมที่ต่างกัน (รูปที่ 29)

ความแตกต่างของระยะทางระหว่างจุดสองจุดบนพื้นผิวโลกตามล็อกโซโดรมและออร์โธโดรมนั้นมีความสำคัญในทางปฏิบัติเฉพาะในระหว่างการข้ามมหาสมุทรขนาดใหญ่เท่านั้น

ภายใต้สภาวะปกติ ความแตกต่างนี้จะถูกละเลย และจะต้องว่ายน้ำในเส้นทางคงที่ เช่น โดยโรโซโดรม

เพื่อให้ได้สมการ ลองใช้โรกโซโดรม (รูปที่ 30, ) สองจุด และ ใน,ระยะห่างระหว่างพวกเขานั้นน้อยมาก การวาดเส้นเมอริเดียนและเส้นขนานผ่านเส้นเหล่านั้น เราจะได้รูปสามเหลี่ยมทรงกลมมุมฉากเบื้องต้น เอบีซีในรูปสามเหลี่ยมนี้ มุมที่เกิดขึ้นจากจุดตัดของเส้นลมปราณกับเส้นขนานจะเป็นมุมฉาก และเป็นมุมด้วย nเอบีเท่ากับหัวเรือก.เกตุ เครื่องปรับอากาศแสดงถึงส่วนของส่วนโค้งของเส้นลมปราณและสามารถแสดงออกได้

ที่ไหน - รัศมีของโลกที่ถือเป็นทรงกลม

Δφ - การเพิ่มละติจูดเบื้องต้น (ความแตกต่างในละติจูด)

ขา NEแสดงถึงส่วนโค้งขนาน

ที่ไหนร - รัศมีคู่ขนาน

Δλ - ความแตกต่างเบื้องต้นในลองจิจูด

จากสามเหลี่ยม OO 1 C เราสามารถหาสิ่งนั้นได้

จากนั้นในรูปแบบสุดท้ายขา NEสามารถแสดงได้ดังนี้:

การหารูปสามเหลี่ยมทรงกลมเบื้องต้น เอบีซีสำหรับแฟลต เราจะเขียน

หลังจากลดแล้ว และแทนที่พิกัดที่เพิ่มขึ้นเล็กน้อยเบื้องต้นด้วยค่าเล็กน้อยที่เราจะมี

ลองรวมนิพจน์ผลลัพธ์ในช่วงตั้งแต่ φ 1, แล 1 ถึง φ 2 λ 2 เมื่อพิจารณาค่า tgK ให้คงที่:

ทางด้านขวาเรามีอินทิกรัลของตาราง หลังจากแทนค่าของมันแล้ว เราจะได้สมการของลอกโซโดรมีบนลูกบอล

การวิเคราะห์สมการนี้ช่วยให้เราสามารถสรุปได้ดังต่อไปนี้:

ที่ทิศทาง 0 และ 180° ล็อกโซโดรมจะกลายเป็นส่วนโค้งของวงกลมใหญ่ - เส้นลมปราณ

ที่เส้นทางที่ 90 และ 270° โรโซโดรมเกิดขึ้นพร้อมกับเส้นขนาน

ลอกโซโดรมตัดเส้นขนานแต่ละเส้นเพียงครั้งเดียว และแต่ละเส้นเมริเดียนมีจำนวนไม่สิ้นสุด เหล่านั้น. หมุนวนไปทางเสาก็ไปไม่ถึง

การล่องเรือในเส้นทางคงที่ นั่นคือ ไปตามโรโซโดรม แม้ว่าจะไม่ใช่ระยะทางที่สั้นที่สุดระหว่างจุดสองจุดบนโลก แต่ก็ให้ความสะดวกอย่างมากแก่นักเดินเรือ

ข้อกำหนดสำหรับแผนภูมิการนำทางทางทะเลสามารถกำหนดได้โดยพิจารณาจากข้อดีของการแล่นไปตามโรโซโดรมและผลลัพธ์ของการวิเคราะห์สมการดังต่อไปนี้

1. ล็อกโซโดรมที่ตัดเส้นเมอริเดียนด้วยมุมคงที่ควรแสดงเป็นเส้นตรง

2. การฉายภาพแผนที่ที่ใช้สร้างแผนที่จะต้องมีมุมเท่ากันเพื่อให้เส้น ทิศทาง และมุมของแผนที่สอดคล้องกับความหมายบนพื้นโลก

3. เส้นเมอริเดียนและเส้นขนาน เช่นเดียวกับเส้นคอร์ส 0, 90, 180° และ 270° ต้องเป็นเส้นตรงตั้งฉากกัน

ระยะทางที่สั้นที่สุดระหว่างจุดสองจุดที่กำหนดบนพื้นผิวโลกซึ่งถือเป็นทรงกลมคือระยะทางที่เล็กกว่าของส่วนโค้งของวงกลมใหญ่ที่ผ่านจุดเหล่านี้ ยกเว้นในกรณีของเรือที่วิ่งตามเส้นเมริเดียนหรือเส้นศูนย์สูตร ออร์โธโดรมจะตัดเส้นเมอริเดียนในมุมที่ต่างกัน ดังนั้นเรือที่วิ่งตามโค้งดังกล่าวจะต้องเปลี่ยนทิศทางอยู่ตลอดเวลา ในทางปฏิบัติจะสะดวกกว่าในการติดตามเส้นทางที่สร้างมุมคงที่กับเส้นเมอริเดียนและแสดงบนแผนที่ในการฉายภาพ Mercator เป็นเส้นตรง - ล็อกโซโดรม อย่างไรก็ตาม ในระยะทางไกล ความแตกต่างในความยาวของออร์โธโดรมและล็อกโซโดรมจะมีค่าที่มีนัยสำคัญ ดังนั้นในกรณีเช่นนี้ จะมีการคำนวณออร์โธโดรมและทำเครื่องหมายจุดกึ่งกลางไว้บนนั้น ซึ่งระหว่างนั้นจะแล่นไปตามล็อกโซโดรม

การฉายภาพการทำแผนที่ที่ตรงตามข้อกำหนดข้างต้นได้รับการเสนอโดย Gerard Cramer (Mercator) นักเขียนแผนที่ชาวดัตช์ในปี 1569 เพื่อเป็นเกียรติแก่ผู้สร้าง การฉายภาพจึงได้รับการตั้งชื่อ พ่อค้า

และใครอยากเรียนรู้เพิ่มเติมอีกบ้าง? ข้อมูลที่น่าสนใจหาข้อมูลเพิ่มเติม บทความต้นฉบับอยู่บนเว็บไซต์ InfoGlaz.rfลิงก์ไปยังบทความที่ทำสำเนานี้ -

DISTANCE ระยะทางเฉลี่ย 1. ช่องว่างที่แยกจุดสองจุด ช่องว่างระหว่างบางสิ่งบางอย่าง ระยะทางที่สั้นที่สุดระหว่างจุดสองจุดในเส้นตรง เขาอยู่ห่างจากเราสองกิโลเมตร “ผู้บังคับบัญชาให้พวกเขาเข้าไปใกล้ที่สุดเท่าที่จะทำได้... พจนานุกรมอูชาโควา

ระยะทาง- คำนาม, p. ใช้แล้ว บ่อยครั้ง สัณฐานวิทยา: (ไม่) อะไร? ห่างไกล ทำไม? ระยะทาง (ดู) อะไร? ระยะทาง อะไรนะ? ระยะทางประมาณอะไร? เกี่ยวกับระยะทาง กรุณา อะไร ระยะทาง (ไม่) อะไร? ระยะทางอะไร? ระยะทาง (ฉันเห็น) อะไร? ระยะทางอะไร? ระยะทาง... พจนานุกรมอธิบายของ Dmitriev

ระยะทาง- ฉัน; พุธ ช่องว่างที่แยกจุดสองจุด วัตถุสองชิ้น ฯลฯ ช่องว่างระหว่างใคร มากกว่า l แม่น้ำที่สั้นที่สุด ระหว่างสองจุด ร. จากบ้านไปโรงเรียน ย้ายไปที่แม่น้ำใกล้เคียง ในระยะเมตรหนึ่งความยาวแขน รู้บางอย่าง รู้สึกบางอย่าง บน… … พจนานุกรมสารานุกรม

ระยะทาง- ฉัน; พุธ ดูสิ่งนี้ด้วย ระยะทาง ก) ช่องว่างที่แยกจุดสองจุด วัตถุสองชิ้น ฯลฯ ช่องว่างระหว่างใคร มากกว่า l ระยะทางที่สั้นที่สุดระหว่างจุดสองจุด ระยะทางจากบ้านไปโรงเรียน เคลื่อนตัวไปในระยะใกล้... พจนานุกรมสำนวนมากมาย

เรขาคณิต- สาขาวิชาคณิตศาสตร์ที่ศึกษาคุณสมบัติของตัวเลขต่างๆ (จุด เส้น มุม วัตถุสองมิติและสามมิติ) ขนาดและตำแหน่งสัมพัทธ์ เพื่อความสะดวกในการสอน เรขาคณิตจะแบ่งออกเป็น planimetry และ Stereometry ใน… … สารานุกรมถ่านหิน

การนำทาง*

การนำทาง- แผนกการเดินเรือ (ดู) ซึ่งมีคำชี้แจงวิธีการกำหนดตำแหน่งของเรือในทะเลโดยใช้เข็มทิศและบันทึก (ดู) การระบุตำแหน่งของเรือในทะเลหมายถึงการวางแผนบนแผนที่ถึงจุดที่เรืออยู่ ช่วงเวลานี้ตั้งอยู่.… … พจนานุกรมสารานุกรม F.A. บร็อคเฮาส์ และ ไอ.เอ. เอโฟรน

โคเฮน- (โคเฮน) แฮร์มันน์ (1842 1918) นักปรัชญาชาวเยอรมัน ผู้ก่อตั้งและตัวแทนที่โดดเด่นที่สุดของโรงเรียน Marburg แห่งลัทธินีโอ-คันเทียน ผลงานหลัก: 'ทฤษฎีประสบการณ์ของคานท์' (พ.ศ. 2428), 'เหตุผลด้านจริยธรรมของคานท์' (พ.ศ. 2420), 'เหตุผลด้านสุนทรียศาสตร์ของคานท์' (พ.ศ. 2432), 'ตรรกะ... ...

คานท์ อิมมานูเอล- เส้นทางชีวิตของคานท์และงานเขียน อิมมานูเอล คานท์เกิดที่เมืองโคนิกส์เบิร์ก (ปัจจุบันคือคาลินินกราด) ในปรัสเซียตะวันออกในปี พ.ศ. 2267 พ่อของเขาเป็นคนขับอานม้า ส่วนแม่ของเขาเป็นแม่บ้าน ลูก 6 คนของพวกเขาไม่ได้มีชีวิตอยู่จนโตเป็นผู้ใหญ่ กานต์ระลึกถึงพ่อแม่ของเขาเสมอจาก... ... ปรัชญาตะวันตกตั้งแต่กำเนิดจนถึงปัจจุบัน

ปรัชญาวิพากษ์วิจารณ์ของคานท์: การสอนเรื่องความสามารถ- (La philosophie critique de Kant: Doctrines des facultes, 1963) ผลงานของ Deleuze Deleuze กล่าวถึงลักษณะวิธีการเหนือธรรมชาติในบทนำว่า Kant เข้าใจปรัชญาในฐานะศาสตร์แห่งความสัมพันธ์ของความรู้ทั้งหมดกับเป้าหมายสำคัญ... ... ประวัติศาสตร์ปรัชญา: สารานุกรม

หลักการฟาร์ม- หลักการพื้นฐานของทัศนศาสตร์เชิงเรขาคณิต (ดูทัศนศาสตร์เชิงเรขาคณิต) รูปแบบที่ง่ายที่สุดของ f.p. คือข้อความที่ว่ารังสีของแสงจะแพร่กระจายในอวกาศระหว่างจุดสองจุดเสมอไปตามเส้นทางซึ่งมีระยะเวลาเดินทางน้อยกว่า... ใหญ่ สารานุกรมโซเวียต

(เรขาคณิตเชิงพรรณนา)
  • ซีดี (CXDX, C2D2)แสดงให้เห็นเป็นจุด ค5 = D5 A5B5เท่ากับ...
    (เรขาคณิตเชิงพรรณนา)
  • การกำหนดระยะห่างระหว่างระนาบสองระนาบขนานกัน
    การหาระยะห่างระหว่างระนาบขนานสองระนาบในตำแหน่งทั่วไป 01| เอ็กซ์สะดวกในการลดปัญหาการกำหนดระยะห่างระหว่างระนาบสองระนาบเดียวกันโดยเปลี่ยนเป็นตำแหน่งของโปรเจ็กเตอร์ ในกรณีนี้ ระยะห่างระหว่างระนาบจะถูกกำหนดเป็นแนวตั้งฉากระหว่างเส้น...
    (เรขาคณิตเชิงพรรณนา)
  • การกำหนดระยะห่างระหว่างเส้นตัดกันสองเส้น
    หากคุณต้องการกำหนดระยะห่างที่สั้นที่สุดระหว่างเส้นตรงสองเส้นที่ตัดกัน คุณต้องเปลี่ยนระบบระนาบการฉายภาพสองครั้ง เมื่อแก้ไขปัญหานี้ให้เป็นเส้นตรง ซีดี (CXDX, C2D2)แสดงให้เห็นเป็นจุด ค5 = D5(รูปที่ 198) ระยะทางจากจุดนี้ถึงการฉายภาพ A5B5เท่ากับ...
    (เรขาคณิตเชิงพรรณนา)
  • มุมระหว่างเส้นตรงสองเส้นที่ตัดกัน
    นี่คือมุมระหว่างเส้นตัดกันสองเส้นขนานกับข้อมูล ดังนั้นงานนี้จึงคล้ายกับงานก่อนหน้า ในการแก้ปัญหาคุณจะต้องใช้จุดใดก็ได้และลากเส้นสองเส้นผ่านมันขนานกับเส้นตัดที่กำหนดและใช้การแปลงของการฉายภาพเพื่อกำหนดมุมที่ต้องการ....
    (ความรู้พื้นฐานของเรขาคณิตเชิงพรรณนา หลักสูตรระยะสั้นและรวบรวมปัญหา)
  • การกำหนดระยะห่างระหว่างเส้นขนานสองเส้น
    ปัญหาได้รับการแก้ไขโดยวิธีการเปลี่ยนระนาบการฉายภาพสองครั้ง ในขั้นตอนสุดท้าย ระนาบการฉายภาพอันใดอันหนึ่งจะต้องตั้งฉากกับเส้นที่ตัดกันเส้นใดเส้นหนึ่ง จากนั้นระยะทางที่สั้นที่สุดระหว่างพวกเขาจะถูกกำหนดโดยขนาดของส่วนตั้งฉากกับเส้นข้ามอีกเส้น (รูปที่ 199)....
    (เรขาคณิตเชิงพรรณนา)
  • เมื่อทำเครื่องหมายสองจุดบนกระดานดำด้วยชอล์กครูจึงเสนองานให้เด็กนักเรียน: วาดเส้นทางที่สั้นที่สุดระหว่างทั้งสองจุด

    หลังจากคิดแล้ว นักเรียนก็ลากเส้นที่คดเคี้ยวระหว่างพวกเขาอย่างระมัดระวัง

    - นั่นเป็นวิธีที่สั้นที่สุด! – อาจารย์รู้สึกประหลาดใจ - ใครสอนคุณเรื่องนั้น?

    - พ่อของฉัน. เขาเป็นคนขับแท็กซี่

    แน่นอนว่าการวาดภาพของเด็กนักเรียนไร้เดียงสานั้นเป็นเพียงเรื่องเล็กๆ น้อยๆ แต่คุณจะไม่ยิ้มไหมถ้าถูกบอกว่าส่วนโค้งประในรูปที่ 1 1 - เส้นทางที่สั้นที่สุดจากแหลมกู๊ดโฮปไปยังปลายสุดทางใต้ของออสเตรเลีย!

    ที่โดดเด่นยิ่งกว่านั้นคือข้อความต่อไปนี้: แสดงในรูป. 2 เส้นทางวงเวียนจากญี่ปุ่นไปคลองปานามานั้นสั้นกว่าเส้นตรงที่ลากระหว่างบนแผนที่เดียวกัน!

    ข้าว. 1. เปิด แผนที่ทะเลเส้นทางที่สั้นที่สุดจากแหลมกู๊ดโฮปไปยังปลายด้านใต้ของออสเตรเลียไม่ได้ระบุเป็นเส้นตรง (“loxodrome”) แต่ระบุด้วยเส้นโค้ง (“orthodrome”)


    ทั้งหมดนี้ดูเหมือนเป็นเรื่องตลก แต่ต่อหน้าคุณกลับกลายเป็นความจริงที่ไม่อาจโต้แย้งได้ ซึ่งเป็นที่รู้จักกันดีในหมู่นักทำแผนที่




    ข้าว. 2. ดูเหมือนเหลือเชื่อที่เส้นทางโค้งที่เชื่อมต่อโยโกฮาม่ากับคลองปานามาบนแผนที่ทะเลนั้นสั้นกว่าเส้นตรงที่ลากระหว่างจุดเดียวกัน


    เพื่อชี้แจงประเด็นนี้ เราจะต้องพูดสักสองสามคำเกี่ยวกับแผนที่โดยทั่วไปและโดยเฉพาะแผนที่ทะเล การแสดงภาพส่วนต่างๆ ของพื้นผิวโลกบนกระดาษไม่ใช่เรื่องง่าย แม้โดยหลักการแล้ว เนื่องจากโลกคือลูกบอล และเป็นที่รู้กันว่าไม่มีส่วนใดของพื้นผิวทรงกลมที่สามารถกางออกบนเครื่องบินได้โดยไม่มีรอยพับและรอยฉีกขาด เราต้องเผชิญกับการบิดเบือนแผนที่อย่างหลีกเลี่ยงไม่ได้ มีการคิดค้นวิธีการวาดแผนที่หลายวิธี แต่แผนที่ทั้งหมดไม่ได้ปราศจากข้อบกพร่อง: บางส่วนมีการบิดเบือนแบบหนึ่งหรือแบบอื่น ๆ แต่ไม่มีแผนที่ใดที่ไม่มีการบิดเบือนเลย

    ลูกเรือใช้แผนที่ที่วาดตามวิธีการของนักเขียนแผนที่และนักคณิตศาสตร์ชาวดัตช์โบราณแห่งศตวรรษที่ 16 เมอร์เคเตอร์ วิธีการนี้เรียกว่า “การฉายภาพแบบ Mercatorian” มันง่ายที่จะจดจำแผนที่ทะเลด้วยตารางสี่เหลี่ยม: เส้นเมอริเดียนจะปรากฎบนนั้นเป็นชุดของเส้นตรงขนานกัน วงกลมละติจูดก็เป็นเส้นตรงเช่นกัน ตั้งฉากกับวงกลมวงแรก (ดูรูปที่ 5)

    ลองนึกภาพตอนนี้ว่าคุณจำเป็นต้องค้นหาเส้นทางที่สั้นที่สุดจากท่าเรือมหาสมุทรหนึ่งไปยังอีกท่าเรือหนึ่งโดยอยู่บนเส้นขนานเดียวกัน บนมหาสมุทร สามารถเข้าถึงทุกเส้นทางได้ และการเดินทางไปที่นั่นตามเส้นทางที่สั้นที่สุดนั้นเป็นไปได้เสมอหากคุณรู้ว่ามันวิ่งอย่างไร ในกรณีของเรา เป็นเรื่องปกติที่จะคิดว่าเส้นทางที่สั้นที่สุดไปตามขนานที่ทั้งสองพอร์ตอยู่: บนแผนที่มันเป็นเส้นตรง และอะไรจะสั้นกว่าเส้นทางตรง! แต่เราคิดผิด: เส้นทางคู่ขนานไม่ได้สั้นที่สุดเลย

    อันที่จริง: บนพื้นผิวของลูกบอล ระยะห่างที่สั้นที่สุดระหว่างจุดสองจุดคือส่วนโค้งของวงกลมใหญ่ที่เชื่อมต่อจุดทั้งสอง แต่วงกลมของเส้นขนาน - เล็ก วงกลม. ส่วนโค้งของวงกลมขนาดใหญ่มีความโค้งน้อยกว่าส่วนโค้งของวงกลมเล็กๆ ใดๆ ที่ลากผ่านจุดสองจุดเดียวกัน รัศมีที่ใหญ่กว่าจะสัมพันธ์กับความโค้งที่เล็กกว่า ยืดด้ายบนโลกระหว่างจุดสองจุดของเรา (รูปที่ 3) รับรองว่าจะไม่นอนขนานกันแต่อย่างใด ด้ายที่ตึงเป็นตัวบ่งชี้ที่เถียงไม่ได้ เส้นทางที่สั้นที่สุดและถ้ามันไม่ตรงกับเส้นขนานบนโลก ดังนั้นบนแผนที่ทะเลเส้นทางที่สั้นที่สุดจะไม่ถูกระบุด้วยเส้นตรง โปรดจำไว้ว่าวงกลมของเส้นขนานนั้นปรากฎบนแผนที่เป็นเส้นตรง แต่เส้นใด ๆ ที่ ไม่ตรงกับเส้นตรงคือ เส้นโค้ง .



    ข้าว. 3. วิธีง่ายๆ ในการค้นหาเส้นทางที่สั้นที่สุดระหว่างจุดสองจุด: คุณต้องดึงด้ายบนโลกระหว่างจุดเหล่านี้


    หลังจากที่ได้กล่าวไปแล้ว ก็ชัดเจนว่าเหตุใดเส้นทางที่สั้นที่สุดบนแผนที่ทะเลจึงไม่ได้แสดงเป็นเส้นตรง แต่เป็นเส้นโค้ง

    พวกเขาบอกว่าเมื่อเลือกทิศทางสำหรับ Nikolaevskaya (ปัจจุบันคือ Oktyabrskaya) ทางรถไฟมีการถกเถียงกันไม่รู้จบว่าจะเลือกเส้นทางไหน การโต้เถียงสิ้นสุดลงโดยการแทรกแซงของซาร์นิโคลัสที่ 1 ผู้ซึ่งแก้ไขปัญหาได้ "ตรงไปตรงมา" อย่างแท้จริง: เขาเชื่อมโยงเซนต์ปีเตอร์สเบิร์กกับมอสโกตามแนวทาง หากทำสิ่งนี้บนแผนที่ Mercator ผลลัพธ์ที่ได้จะเป็นเรื่องที่น่าอับอาย แทนที่จะเป็นถนนเส้นตรง ถนนกลับกลายเป็นทางคดเคี้ยว

    ใครก็ตามที่ไม่หลีกเลี่ยงการคำนวณสามารถตรวจสอบให้แน่ใจว่าด้วยการคำนวณง่ายๆ ว่าเส้นทางที่ดูคดเคี้ยวสำหรับเราบนแผนที่นั้นสั้นกว่าเส้นทางที่เราพร้อมที่จะพิจารณาโดยตรง ให้ท่าเรือทั้งสองของเราอยู่บนเส้นขนานที่ 60 และอยู่ห่างกัน 60° (แน่นอนว่าท่าเรือทั้งสองนั้นมีอยู่จริงหรือไม่นั้นก็ไม่สำคัญต่อการคำนวณ)



    ข้าว. 4. การคำนวณระยะทางระหว่างจุด A และ B บนลูกบอลตามส่วนโค้งขนานและตามส่วนโค้งวงกลมใหญ่


    ในรูป 4 จุด เกี่ยวกับ -ศูนย์ โลก, เอบี –ส่วนโค้งของวงกลมละติจูดที่ท่าเรืออยู่ เอ และ บี; วีอุณหภูมิ 60° ศูนย์กลางของวงกลมละติจูดอยู่ที่จุดนั้น กับลองจินตนาการว่าจากศูนย์กลาง เกี่ยวกับลูกโลกถูกลากผ่านท่าเรือเดียวกันด้วยส่วนโค้งของวงกลมใหญ่: รัศมีของมัน OB = โอเอ = ร;มันจะผ่านไปใกล้กับส่วนโค้งที่วาดไว้ เอบี,แต่จะไม่เกิดขึ้นพร้อมๆ กัน

    ลองคำนวณความยาวของแต่ละส่วนโค้งกัน ตั้งแต่จุด และ ในอยู่ที่ละติจูด 60° แล้วตามด้วยรัศมี โอเอและ อ.บจำนวนเงินที่จะ ระบบปฏิบัติการ(แกนของโลก) ทำมุม 30° ในรูปสามเหลี่ยมมุมฉาก อสขา ไฟฟ้ากระแสสลับ (=r)วางตรงข้ามกับมุม 30° เท่ากับครึ่งหนึ่งของด้านตรงข้ามมุมฉาก เจเอสซี;

    วิธี, r=R/2ความยาวส่วนโค้ง เอบีคือหนึ่งในหกของความยาวของวงกลมละติจูด และเนื่องจากวงกลมนี้มีความยาวครึ่งหนึ่งของวงกลมใหญ่ (เท่ากับครึ่งหนึ่งของรัศมี) ดังนั้นความยาวส่วนโค้งของวงกลมเล็ก



    ในการหาความยาวของส่วนโค้งของวงกลมใหญ่ที่ลากระหว่างจุดเดียวกัน (เช่น เส้นทางที่สั้นที่สุดระหว่างจุดเหล่านั้น) เราจำเป็นต้องหาขนาดของมุม เอโอบี.คอร์ด เช่นซึ่งรองรับส่วนโค้ง 60° (ของวงกลมเล็ก) คือด้านของรูปหกเหลี่ยมปกติที่จารึกไว้ในวงกลมเล็กวงเดียวกัน นั่นเป็นเหตุผล เอบี = r=R/2

    เมื่อวาดเส้นตรงแล้ว โอ.ดี.เชื่อมต่อศูนย์กลาง เกี่ยวกับลูกโลกที่มีตรงกลาง ดีคอร์ด เอบี,เราได้สามเหลี่ยมมุมฉาก โอดะ,มุมอยู่ที่ไหน ด –ตรง:

    DA= 1/2 AB และ OA = R

    ซินAOD=โฆษณา: AO=R/4:R=0.25

    จากที่นี่เราพบ (จากตาราง):

    =14°28",5

    และดังนั้นจึง

    = 28°57".

    ตอนนี้การหาความยาวที่ต้องการของเส้นทางที่สั้นที่สุดในหน่วยกิโลเมตรไม่ใช่เรื่องยาก การคำนวณอาจง่ายขึ้นหากเราจำไว้ว่าความยาวของหนึ่งนาทีของวงกลมใหญ่ของโลกคือ

    เราเรียนรู้ว่าเส้นทางตามวงกลมละติจูดซึ่งแสดงบนแผนที่ทะเลเป็นเส้นตรงคือ 3333 กม. และเส้นทางตามวงกลมใหญ่ - ตามแนวโค้งบนแผนที่ - คือ 3213 กม. หรือสั้นกว่า 120 กม.

    ด้วยด้ายและมีลูกโลกอยู่ในมือ คุณสามารถตรวจสอบความถูกต้องของภาพวาดของเราได้อย่างง่ายดาย และตรวจสอบให้แน่ใจว่าส่วนโค้งของวงกลมใหญ่อยู่จริงๆ ดังที่แสดงในภาพวาด แสดงในรูปที่. 1 ถูกกล่าวหาว่าเส้นทางทะเล "ตรง" จากแอฟริกาไปยังออสเตรเลียคือ 6,020 ไมล์ และ "ทางโค้ง" คือ 5,450 ไมล์ กล่าวคือ สั้นกว่า 570 ไมล์หรือ 1,050 กม. เส้นทางทางอากาศ "โดยตรง" จากลอนดอนไปยังเซี่ยงไฮ้บนแผนที่ทะเลตัดทะเลแคสเปียน ในขณะที่เส้นทางที่สั้นที่สุดวิ่งไปทางเหนือของเซนต์ปีเตอร์สเบิร์ก เป็นที่ชัดเจนว่าปัญหาเหล่านี้มีบทบาทอย่างไรในการประหยัดเวลาและเชื้อเพลิง

    หากในยุคของการเดินเรือเวลาการเดินเรือไม่ได้มีค่าเสมอไป - ดังนั้น "เวลา" ยังไม่ถือเป็น "เงิน" - ดังนั้นด้วยการกำเนิดของเรือกลไฟเราจะต้องจ่ายค่าถ่านหินทุกตันที่ใช้มากเกินไป นั่นเป็นเหตุผลว่าทำไมทุกวันนี้ เรือจึงถูกนำทางไปตามเส้นทางที่สั้นที่สุด โดยมักจะใช้แผนที่ที่ไม่ได้สร้างขึ้นในการฉายภาพ Mercator แต่ในการฉายภาพที่เรียกว่า "ศูนย์กลาง": บนแผนที่เหล่านี้ ส่วนโค้งของวงกลมใหญ่จะแสดงเป็นเส้นตรง

    เหตุใดนักเดินเรือรุ่นก่อนจึงใช้แผนที่หลอกลวงและเลือกเส้นทางที่ไม่เอื้ออำนวย เป็นความผิดพลาดที่จะคิดว่าในสมัยก่อนพวกเขาไม่รู้เกี่ยวกับคุณลักษณะที่ระบุไว้ในปัจจุบันของแผนภูมิทะเล แน่นอนว่าเรื่องนี้ได้รับการอธิบายไม่ใช่จากสิ่งนี้ แต่จากข้อเท็จจริงที่ว่าแผนที่ที่วาดตามวิธีของ Mercator มีประโยชน์ที่มีคุณค่ามากสำหรับลูกเรือควบคู่ไปกับความไม่สะดวก ประการแรก แผนที่ดังกล่าวแสดงให้เห็นส่วนเล็กๆ ของพื้นผิวโลกโดยไม่บิดเบือน โดยคงมุมของเส้นขอบไว้ สิ่งนี้ไม่ได้ขัดแย้งกับความจริงที่ว่าเมื่ออยู่ห่างจากเส้นศูนย์สูตร รูปทรงทั้งหมดจะยืดออกอย่างเห็นได้ชัด ในละติจูดสูง การยืดออกมีความสำคัญมากจนแผนที่ทะเลทำให้บุคคลที่ไม่คุ้นเคยกับคุณลักษณะของแผนที่มีแนวคิดที่ผิดอย่างสิ้นเชิงเกี่ยวกับขนาดที่แท้จริงของทวีปต่างๆ กรีนแลนด์ดูเหมือนมีขนาดเท่ากับแอฟริกา อลาสก้ามีขนาดใหญ่กว่าออสเตรเลีย แม้ว่ากรีนแลนด์จะใหญ่ก็ตาม มีขนาดเล็กกว่าแอฟริกา 15 เท่า และอลาสกาและกรีนแลนด์มีขนาดเป็นครึ่งหนึ่งของออสเตรเลีย แต่กะลาสีเรือที่คุ้นเคยกับคุณลักษณะเหล่านี้ของแผนที่เป็นอย่างดีจะไม่สามารถเข้าใจผิดได้ เขาทนกับสิ่งเหล่านี้ โดยเฉพาะอย่างยิ่งเมื่อภายในพื้นที่เล็กๆ แผนภูมิทะเลให้ความคล้ายคลึงกับธรรมชาติทุกประการ (รูปที่ 5)

    แต่แผนภูมิเดินเรือช่วยแก้ปัญหาการฝึกเดินเรือได้อย่างมาก นี่เป็นแผนที่ประเภทเดียวที่แสดงเส้นทางของเรือที่เคลื่อนที่ในเส้นทางคงที่เป็นเส้นตรง การเดินบน “เส้นทางคงที่” หมายถึง การยึดมั่นในทิศทางเดียวอย่างสม่ำเสมอ หรือ “จุดอ้างอิง” จุดเดียวที่เฉพาะเจาะจง หรืออีกนัยหนึ่งคือ เดินในลักษณะที่ตัดเส้นลมปราณทั้งหมดด้วยมุมที่เท่ากัน แต่เส้นทางนี้ ("โลกโซโดรม") สามารถแสดงเป็นเส้นตรงได้เฉพาะบนแผนที่ซึ่งเส้นเมอริเดียนทั้งหมดเป็นเส้นตรงขนานกัน และเนื่องจากบนโลก วงกลมละติจูดตัดกับเส้นเมอริเดียนเป็นมุมฉาก ดังนั้นบนแผนที่ดังกล่าว วงกลมละติจูดจึงควรเป็นเส้นตรงตั้งฉากกับเส้นของเส้นเมอริเดียน กล่าวโดยย่อคือ เรามาถึงตารางพิกัดที่ประกอบเป็นคุณลักษณะเฉพาะของแผนที่ทะเลอย่างแม่นยำ




    ข้าว. 5. แผนที่เดินเรือหรือแผนที่ Mercator ของโลก แผนที่ดังกล่าวทำให้ขนาดของรูปทรงที่อยู่ห่างจากเส้นศูนย์สูตรเกินจริงอย่างมาก ตัวอย่างเช่น อะไรใหญ่กว่า: กรีนแลนด์หรือออสเตรเลีย (ตอบเป็นข้อความ)


    ความชื่นชอบของกะลาสีเรือสำหรับแผนที่ของ Mercator เป็นที่เข้าใจแล้ว เมื่อต้องการกำหนดเส้นทางที่ต้องปฏิบัติตามเมื่อไปยังท่าเรือที่กำหนด นักเดินเรือจะใช้ไม้บรรทัดที่จุดสิ้นสุดของเส้นทางและวัดมุมที่ทำกับเส้นเมอริเดียน อยู่ในทะเลเปิดตลอดเวลาในทิศทางนี้นักเดินเรือจะนำเรือไปยังเป้าหมายได้อย่างแม่นยำ คุณจะเห็นว่า "ล็อกโซโดรม" แม้ว่าจะไม่ใช่เส้นทางที่สั้นที่สุดและไม่ประหยัดที่สุด แต่ในแง่หนึ่งก็เป็นเส้นทางที่สะดวกมากสำหรับกะลาสีเรือ ตัวอย่างเช่น หากต้องการไปถึงจากแหลมกู๊ดโฮปไปจนถึงปลายด้านใต้ของออสเตรเลีย (ดูรูปที่ 1) เราจะต้องอยู่ในเส้นทางเดียวกันเสมอ S 87°.50" ขณะเดียวกัน เพื่อนำเรือไปสู่จุดสุดท้ายเดียวกัน จุด เส้นทางที่สั้นที่สุด(ตาม “ออร์โธโดรม”) ดังที่เห็นจากภาพ จำเป็นต้องเปลี่ยนทิศทางของเรืออย่างต่อเนื่อง: เริ่มต้นด้วยเส้นทาง S 42°.50" และจบด้วยเส้นทาง N 53°.50 " (ในกรณีนี้ เส้นทางที่สั้นที่สุดไม่สามารถทำได้ด้วยซ้ำ - มันวางอยู่ในกำแพงน้ำแข็งแอนตาร์กติก)

    ทั้งสองเส้นทาง - ตาม "loxodrome" และตาม "orthodrome" - เกิดขึ้นเฉพาะเมื่อมีการแสดงเส้นทางตามวงกลมใหญ่บนแผนภูมิทะเลเป็นเส้นตรง: เมื่อเคลื่อนที่ไปตามเส้นศูนย์สูตรหรือตามเส้นลมปราณ ในกรณีอื่นๆ ทั้งหมด เส้นทางเหล่านี้จะแตกต่างออกไป

    อัลกอริทึมของ Dijkstra เป็นอัลกอริทึมกราฟที่คิดค้นโดยนักวิทยาศาสตร์ชาวดัตช์ Edsger Dijkstra ในปี 1959 ค้นหาเส้นทางที่สั้นที่สุดจากจุดยอดจุดหนึ่งของกราฟไปยังจุดยอดอื่นๆ ทั้งหมด อัลกอริธึมทำงานได้ สำหรับกราฟที่ไม่มีขอบที่มีน้ำหนักติดลบเท่านั้น

    ลองพิจารณาการดำเนินการของอัลกอริทึมโดยใช้ตัวอย่างกราฟที่แสดงในรูป

    สมมติว่าคุณจำเป็นต้องค้นหาระยะทางที่สั้นที่สุดจากจุดยอดที่ 1 ไปยังจุดยอดอื่นๆ ทั้งหมด

    วงกลมแสดงถึงจุดยอด เส้นระบุเส้นทางระหว่างจุดยอด (ขอบของกราฟ) ตัวเลขของจุดยอดจะแสดงอยู่ในวงกลมและ "ราคา" ของจุดยอดจะแสดงอยู่เหนือขอบ - ความยาวของเส้นทาง ถัดจากจุดยอดแต่ละจุดจะมีเครื่องหมายสีแดง - ความยาวของเส้นทางที่สั้นที่สุดไปยังจุดยอดนี้จากจุดยอด 1

    ขั้นแรก. ลองดูขั้นตอนของอัลกอริทึมของ Dijkstra สำหรับตัวอย่างของเรา จุดยอด 1 มีป้ายกำกับขั้นต่ำ เพื่อนบ้านคือจุดยอด 2, 3 และ 6

    เพื่อนบ้านคนแรกของจุดยอด 1 คือจุดยอด 2 เนื่องจากความยาวของเส้นทางไปยังจุดนั้นน้อยมาก ความยาวของเส้นทางที่ทะลุผ่านจุดยอด 1 เท่ากับผลรวมของค่าของป้ายของจุดยอด 1 และความยาวของขอบที่เริ่มจากอันดับที่ 1 ถึง 2 นั่นคือ 0 + 7 = 7 ซึ่งน้อยกว่า ป้ายปัจจุบันของจุดยอด 2 อนันต์ ดังนั้นป้ายใหม่คือจุดยอดที่ 2 คือ 7

    เราทำการดำเนินการที่คล้ายกันกับเพื่อนบ้านอีกสองคนของจุดยอดที่ 1 - ที่ 3 และ 6

    มีการตรวจสอบเพื่อนบ้านทั้งหมดของจุดยอด 1 ระยะทางต่ำสุดในปัจจุบันถึงจุดยอด 1 ถือเป็นที่สิ้นสุดและไม่สามารถแก้ไขได้ (ซึ่งในกรณีนี้ได้รับการพิสูจน์ครั้งแรกโดย E. Dijkstra) ลองขีดฆ่าออกจากกราฟเพื่อทำเครื่องหมายว่ามีการเยี่ยมชมจุดยอดนี้แล้ว

    ขั้นตอนที่สอง. ขั้นตอนอัลกอริธึมจะถูกทำซ้ำ เราพบจุดยอดที่ "ใกล้ที่สุด" ที่ไม่มีใครเยี่ยมชมอีกครั้ง นี่คือจุดยอด 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

    การใช้อัลกอริทึมในภาษาการเขียนโปรแกรมต่างๆ:

    ซี++

    #รวม "stdafx.h" #รวม ใช้เนมสเปซมาตรฐาน; ค่าคงที่ V=6; //อัลกอริทึมของ Dijkstra เป็นโมฆะ Dijkstra(int GR[V][V], int st) ( int Distance[V], count, index, i, u, m=st+1; bool visit[V]; for (i= 0;ผม "< "<> "; cin>>start; Dijkstra(GR, start-1); system("หยุดชั่วคราว>>โมฆะ"); )

    ปาสคาล

    โปรแกรม DijkstraAlgorithm; ใช้ crt; ค่าคงที่ V=6; อินฟ=100000; พิมพ์ vector=array ของจำนวนเต็ม; เริ่มต้น var: จำนวนเต็ม; 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) ขั้นตอน Dijkstra(GR: อาร์เรย์ของจำนวนเต็ม; st: จำนวนเต็ม); จำนวนนับ, ดัชนี, i, u, m, min: จำนวนเต็ม; ระยะทาง: เวกเตอร์; เยี่ยมชม: อาร์เรย์ของบูลีน; เริ่ม ม.:=st; สำหรับ i:=1 ถึง V จะเริ่มต้นระยะทาง[i]:=inf; เยี่ยมชม [i]:=false; จบ; ระยะทาง:=0; สำหรับการนับ:=1 ถึง V-1 ให้เริ่มต้น min:=inf; สำหรับ i:=1 ถึง V ทำ if (ไม่ได้เข้าชม[i]) และ (ระยะทาง[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]) อย่างอื่น writeln(m," > ", i," = ", "เส้นทางไม่พร้อมใช้งาน"); จบ; (บล็อกหลักของโปรแกรม) เริ่มต้น clrscr; write("เริ่มจุดยอด >> "); อ่าน(เริ่ม); ไดจ์คสตรา(GR, สตาร์ท); จบ.

    ชวา

    นำเข้า java.io.BufferedReader; นำเข้า java.io.IOException; นำเข้า java.io.InputStreamReader; นำเข้า java.io.PrintWriter; นำเข้า java.util.ArrayList; นำเข้า java.util.Arrays; นำเข้า java.util.StringTokenizer; โซลูชันคลาสสาธารณะ ( private static int INF = Integer.MAX_VALUE / 2; int ส่วนตัว n; // จำนวนจุดยอดใน digraph ส่วนตัว int m; // จำนวนส่วนโค้งใน digraph ArrayList ส่วนตัว adj; //รายการ adjacency ArrayList ส่วนตัว น้ำหนัก; //น้ำหนักของขอบในไดกราฟส่วนตัวบูลีนที่ใช้; //อาร์เรย์สำหรับจัดเก็บข้อมูลเกี่ยวกับจุดยอด int dist ส่วนตัวที่ทะลุผ่านและไม่ผ่านทะลุ; //อาร์เรย์สำหรับจัดเก็บระยะห่างจากจุดสุดยอดเริ่มต้น //อาร์เรย์ของบรรพบุรุษที่จำเป็นในการกู้คืนเส้นทางที่สั้นที่สุดจากจุดเริ่มต้นส่วนตัว int pred; อินท์เริ่มต้น; //เริ่มต้นจุดยอดซึ่งห่างจากจุดยอดอื่น ๆ ทั้งหมดที่ต้องการหา BufferedReader ส่วนตัว cin; ศาล PrintWriter ส่วนตัว; โทเค็น StringTokenizer ส่วนตัว; // ขั้นตอนในการเรียกใช้อัลกอริทึมของ Dijkstra จากจุดสุดยอดเริ่มต้น 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 = ( new Graph.Edge("a", "b", 7), new Graph.Edge("a", "c", 9), new Graph.Edge( "a", "f", 14), new Graph.Edge("b", "c", 10), new Graph.Edge("b", "d", 15), new Graph.Edge("c ", "d", 11), new Graph.Edge("c", "f", 2), new Graph.Edge("d", "e", 6), new Graph.Edge("e", "f", 9), ); สตริงสุดท้ายคงที่ส่วนตัว START = "a"; สตริงสุดท้ายคงที่ส่วนตัว END = "e"; โมฆะคงที่สาธารณะ main(String args) (กราฟ g = กราฟใหม่ (GRAPH); g.dijkstra (START); g.printPath(END); //g.printAllPaths(); ) ) กราฟคลาส (แผนที่สุดท้ายส่วนตัว กราฟ; // การแมปชื่อจุดยอดกับวัตถุ Vertex สร้างขึ้นจากชุดของ Edges /** ขอบด้านหนึ่งของกราฟ (ใช้โดยตัวสร้างกราฟเท่านั้น) */ 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; ) ) /** จุดยอดหนึ่งของกราฟ พร้อมด้วยการแมปกับจุดยอดที่อยู่ติดกัน */ Vertex คลาสคงที่สาธารณะนำไปใช้เปรียบเทียบได้ ( ชื่อสตริงสุดท้ายสาธารณะ; public int dist = Integer.MAX_VALUE; // MAX_VALUE ถือว่าเป็นอนันต์ สาธารณะ Vertex ก่อนหน้า = null; แผนที่สุดท้ายสาธารณะ เพื่อนบ้าน = HashMap ใหม่<>(); จุดสุดยอดสาธารณะ (ชื่อสตริง) ( this.name = name; ) โมฆะส่วนตัว 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 comparisonTo(Vertex other) ( return Integer.compare(dist, other.dist); ) ) /** สร้างกราฟจากชุดของขอบ * / กราฟสาธารณะ(ขอบขอบ) ( กราฟ = ใหม่ 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: edge) ( graph.get(e.v1) Neighbors.put(graph.get(e.v2), e.dist); //graph.get(e.v2).neighbors.put(graph.get(e.v1), e.dist); // ยัง ทำสิ่งนี้สำหรับกราฟที่ไม่มีทิศทาง ) ) /** รัน dijkstra โดยใช้จุดสุดยอดแหล่งที่ระบุ */ public void dijkstra(String startName) ( if (!graph.containsKey(startName)) ( System.err.printf("Graph does"t มี start vertex \"%s\"\n", startName); return; ) สุดท้าย Vertex source = graph.get(startName); NavigableSet q = TreeSet ใหม่<>(); // ตั้งค่าจุดยอดสำหรับ (Vertex v: graph.values()) ( v.previous = v == source ? source: null; v.dist = v == source ? 0: Integer.MAX_VALUE; q.add( v); ) dijkstra(q); ) /** การใช้อัลกอริทึมของ dijkstra โดยใช้ฮีปไบนารี */ โมฆะส่วนตัว dijkstra(final NavigableSet q) ( Vertex u, v; while (!q.isEmpty()) ( u = q.pollFirst(); // จุดยอดที่มีระยะทางสั้นที่สุด (การวนซ้ำครั้งแรกจะส่งคืนแหล่งที่มา) ถ้า (u.dist == Integer.MAX_VALUE) ทำลาย // เราสามารถเพิกเฉยต่อคุณ (และจุดยอดอื่น ๆ ที่เหลือ) เนื่องจากไม่สามารถเข้าถึงได้ // ดูระยะทางไปยังเพื่อนบ้านแต่ละคนเพื่อดู (Map.Entry a: u.neighbours.entrySet()) ( v = a.getKey(); // เพื่อนบ้านในการวนซ้ำนี้ขั้นสุดท้าย int AlternativeDist = u.dist + a.getValue(); if (alternateDist< v.dist) { // shorter path to neighbour found q.remove(v); v.dist = alternateDist; v.previous = u; q.add(v); } } } } /** Prints a path from the source to the specified vertex */ public void printPath(String endName) { if (!graph.containsKey(endName)) { System.err.printf("Graph doesn"t contain end vertex \"%s\"\n", endName); return; } graph.get(endName).printPath(); System.out.println(); } /** Prints the path from the source to every vertex (output order is not guaranteed) */ public void printAllPaths() { for (Vertex v: graph.values()) { v.printPath(); System.out.println(); } } }

    #รวม #รวม #รวม //#define BIG_EXAMPLE typedef struct node_t node_t, *heap_t; typedef โครงสร้าง edge_t edge_t; struct edge_t ( node_t *nd; /* เป้าหมายของ edge นี้ */ edge_t *sibling;/* สำหรับรายการที่เชื่อมโยงเดี่ยว */ int len; /* edge cost */ ); struct node_t ( edge_t *edge; /* รายการขอบที่เชื่อมโยงเดี่ยว ๆ */ node_t *via; /* โดยที่โหนดก่อนหน้าอยู่ในเส้นทางที่สั้นที่สุด */ double dist; /* ระยะทางจากโหนดต้นทาง */ ชื่อถ่าน; /* the, er , name */ int heap_idx; /* ลิงก์ไปยังตำแหน่งฮีปเพื่ออัพเดตระยะทาง */ ); /* --- การจัดการขอบ --- */ #ifdef BIG_EXAMPLE # กำหนด BLOCK_SIZE (1024 * 32 - 1) #else # กำหนด BLOCK_SIZE 15 #endif edge_t *edge_root = 0, *e_next = 0; /* ไม่ต้องสนใจเรื่องการจัดการหน่วยความจำ มันนอกเหนือประเด็น แกล้งทำเป็น 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(ขนาดของ(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; ) เป็นโมฆะ free_edges() ( สำหรับ (; 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 */ for (; i > 1 && nd->dist< heap->แยก; i = j) (ฮีป[i] = ฮีป[j])->heap_idx = i; ฮีป[i] = nd; nd->heap_idx = ฉัน; ) node_t * pop_queue() ( node_t *nd, *tmp; int i, j; if (!heap_len) return 0; /* ลบองค์ประกอบนำหน้า, ดึงองค์ประกอบส่วนท้ายตรงนั้นแล้วดาวน์ฮีป */ nd = heap; tmp = heap; for (ผม = 1; ผม< heap_len && (j = i * 2) <= heap_len; i = j) { if (j < heap_len && heap[j]->dist > ฮีป -> dist) j ++; ถ้า (ฮีป[j]->dist >= tmp->dist) แตก; (ฮีป[i] = ฮีป[j])->heap_idx = i; ) ฮีป[i] = ทีเอ็มพี; tmp->heap_idx = ฉัน; กลับ 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->ชื่อ); else if (!nd->via) printf("%s(unreached)", nd->name); else ( show_path(nd->via); printf("- > %s(%g) ", nd->ชื่อ, nd->dist); ) ) int main(void) ( #ifndef BIG_EXAMPLE int i; # กำหนด N_NODES ("f" - "a" + 1) node_t * โหนด = calloc (ขนาดของ (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, "ต้นทุน" => $edge); $neighbors[$edge] = array("end" => $edge, "cost" => $edge); ) $vertices = array_unique($vertices); foreach ($จุดยอดเป็น $vertex) ( $dist[$vertex] = INF; $previous[$vertex] = NULL; ) $dist[$source] = 0; $Q = $จุดยอด; while (count($Q) > 0) ( // TODO - ค้นหาวิธีที่เร็วกว่าในการรับ $min = INF; foreach ($Q as $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";


    หลาม

    จากคอลเลกชั่นนำเข้าชื่อทูเพิล คิวจาก pprint นำเข้า pprint เป็น pp inf = float("inf") Edge = nametuple("Edge", "start, end, cost") คลาสกราฟ (): def __init__(self, edges): self .edges = edges2 = self.vertices = set(sum(( for e in edges2, )) def dijkstra(self, source, dest): ยืนยันแหล่งที่มาใน self.vertices dist = (จุดยอด: inf สำหรับจุดยอดใน self.vertices ) Previous = (จุดยอด: ไม่มีสำหรับจุดยอดใน self.vertices) dist = 0 q = self.vertices.copy() Neighbors = (จุดยอด: set() สำหรับจุดยอดใน self.vertices) สำหรับการเริ่มต้น สิ้นสุด ต้นทุนใน self.edge : Neighbors.add((end, cost)) #pp(neighbors) ในขณะที่ q: u = min(q, key=lambda vertex: dist) q.remove(u) if dist[u] == inf หรือ u = = ปลายทาง: แบ่งสำหรับ 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"]