-
當前位置:首頁 > 創(chuàng)意學院 > 技術 > 專題列表 > 正文
如何求最短路徑(如何求最短路徑數(shù)據(jù)結構)
大家好!今天讓創(chuàng)意嶺的小編來大家介紹下關于如何求最短路徑的問題,以下是小編對此問題的歸納整理,讓我們一起來看看吧。
開始之前先推薦一個非常厲害的Ai人工智能工具,一鍵生成原創(chuàng)文章、方案、文案、工作計劃、工作報告、論文、代碼、作文、做題和對話答疑等等
只需要輸入關鍵詞,就能返回你想要的內(nèi)容,越精準,寫出的就越詳細,有微信小程序端、在線網(wǎng)頁版、PC客戶端
官網(wǎng):https://ai.de1919.com。
創(chuàng)意嶺作為行業(yè)內(nèi)優(yōu)秀的企業(yè),服務客戶遍布全球各地,如需了解SEO相關業(yè)務請撥打電話175-8598-2043,或添加微信:1454722008
本文目錄:
一、求A到B之間的最短路徑,怎么獲取
問題:從某頂點出發(fā),沿圖的邊到達另一頂點所經(jīng)過的路徑中,各邊上權值之和最小的一條路徑——最短路徑。解決最短路的問題有以下算法,Dijkstra算法,Bellman-Ford算法,F(xiàn)loyd算法和SPFA算法,另外還有著名的啟發(fā)式搜索算法A*,不過A*準備單獨出一篇,其中Floyd算法可以求解任意兩點間的最短路徑的長度。任意一個最短路算法都是基于這樣一個事實:從任意節(jié)點A到任意節(jié)點B的最短路徑不外乎2種可能,1是直接從A到B,2是從A經(jīng)過若干個節(jié)點到B。
(1) 迪杰斯特拉(Dijkstra)算法按路徑長度(看下面表格的最后一行,就是next點)遞增次序產(chǎn)生最短路徑。先把V分成兩組:
S:已求出最短路徑的頂點的集合
V-S=T:尚未確定最短路徑的頂點集合
將T中頂點按最短路徑遞增的次序加入到S中,依據(jù):可以證明V0到T中頂點Vk的最短路徑,或是從V0到Vk的直接路徑的權值或是從V0經(jīng)S中頂點到Vk的路徑權值之和(反證法可證,說實話,真不明白哦)。
(2) 求最短路徑步驟
初使時令 S={V0},T={其余頂點},T中頂點對應的距離值, 若存在<V0,Vi>,為<V0,Vi>弧上的權值(和SPFA初始化方式不同),若不存在<V0,Vi>,為Inf。
從T中選取一個其距離值為最小的頂點W(貪心體現(xiàn)在此處),加入S(注意不是直接從S集合中選取,理解這個對于理解vis數(shù)組的作用至關重要),對T中頂點的距離值進行修改:若加進W作中間頂點,從V0到Vi的距離值比不加W的路徑要短,則修改此距離值(上面兩個并列for循環(huán),使用最小點更新)。
重復上述步驟,直到S中包含所有頂點,即S=V為止(說明最外層是除起點外的遍歷)。
二、最短路徑求最值12個模型詳解
最短路徑求最值12個模型詳解見下:
問題一:在直線 l 上求一點 P,使得 PA + PB 值最小 .
作法:連接 AB,與直線 l 的交點即為 P 點 .
原理:兩點之間線段最短 . PA + PB 最小值為 AB .
問題二:(“將軍飲馬問題”)在直線 l 上求一點 P,使得 PA + PB 值最小 .
作法:作點 B 關于直線 l 的對稱點 B',連接 AB' 與 l 的交點即為點 P.
原理:兩點之間線段最短. PA + PB 最小值為 AB' .
問題三:在直線 l1、l2 上分別求點 M、N,使得 △PMN 的周長最?。?/p>
作法:分別作點 P 關于兩條直線的對稱點 P' 和 P'',連接 P'P'',與兩條直線的交點即為點 M,N.
原理:兩點之間線段最短. PM + MN + PN 的最小值為線段 P'P'' 的長.
問題四:在直線 l1、l2 上分別求點 M、N,使四邊形 PQMN 的周長最?。?/p>
作法:分別作點 Q 、P 關于直線 l1、l2 的對稱點 Q' 和 P' 連接 Q'P',與兩直線交點即為點 M,N.
原理:兩點之間線段最短. 四邊形 PQMN 周長的最小值為線段 Q'P' + PQ 的長.
問題五:(“造橋選址問題”)直線 m∥n,在 m、n 上分別求點 M、N,使 MN⊥m,
且 AM + MN + BN 的值最小.
作法:將點 A 向下平移 MN 的長度單位得 A',連接 A'B,交 n 于點 N,過 N 作 NM⊥m 于 M .
原理:兩點之間線段最短 . AM + MN + BN 的最小值為 A'B + MN .
問題六:在直線 l 上求兩點 M , N (M 在左),使 MN = a , 并使 AM + MN + NB 的值最小 .
作法:將點 A 向右平移 a 個長度單位得 A',作 A' 關于直線 l 的對稱點 A'',連接 A''B 交直線 l 于點 N,
將 N 點向左平移 a 個單位得 M .
原理:兩點之間線段最短 . AM + MN + NB 的最小值為 A''B + MN .
問題七:在 l1 上求點 A,在 l2 上求點 B,使 PA + AB 值最小 .
作法:作點 P 關于 l1 的對稱點 P',作 P'B⊥l2 于點 B,交 l1 于點 A .
原理:點到直線,垂線段的距離最短 . PA + AB 的最小值為線段 P'B 的長 .
問題八:A 為 l1上一定點,B 為 l2 上一定點,在 l2 上求點 M,在 l1上求點 N,
使 AM + MN + NB 的值最小 .
作法:作點 A 關于 l2 的對稱點 A' , 點 B 關于 l1 的對稱點 B',連接 A'B' 交 l2 于點 M,交 l1 于點 N.
原理:兩點之間線段最短. AM + MN + NB 的最小值為線段 A'B' 的長.
問題九:在直線 l 上求一點 P,使 | PA - PB | 的值最?。?/p>
作法:連接 AB,作 AB 的中垂線與直線 l 的交點即為 P 點.
原理:垂直平分上的點到線段兩端點的距離相等. | PA - PB | = 0 .
問題十:在直線 l 上求一點 P,使 | PA - PB | 的值最大.
作法:作直線 AB,與直線 l 的交點即為 P 點.
原理:三角形任意兩邊之差小于第三邊. | PA - PB | ≤ AB , | PA - PB | 的最大值 = AB .
問題十一:在直線 l 上求一點 P,使 | PA - PB | 的值最大.
作法:作點 B 關于直線 l 的對稱點 B' 作直線 AB',與直線 l 的交點即為 P 點.
原理:三角形任意兩邊之差小于第三邊. | PA - PB | ≤ AB' , | PA - PB | 的最大值 = AB' .
問題十二:(“費馬點”)△ABC 中每一內(nèi)角都小于 120°,在 △ABC 內(nèi)求一點 P,
使得 PA + PB + PC 的值最小 .
作法:所求點為 “費馬點” ,即滿足 ∠APB = ∠BPC = ∠APC = 120° .
以 AB 、 AC 為邊向外作等邊 △ABD、△ACE,連接 CD、BE 相交于點 P,點 P 即為所求 .
原理:兩點之間線段最短 . PA + PB + PC 的最小值 = CD .
三、數(shù)據(jù)結構求最短路徑
用Dijkstra算法求從V1頂點到其他各頂點的最短距離和最短路徑的C語言程序如下
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define N 6 // 頂點數(shù)
#define INF 32767
int adj_arr[N][N] = {{INF, 2, 3, INF, INF, INF},
{INF, INF, INF, 5, INF, INF},
{INF, INF, INF, 3, 10, INF},
{INF, INF, INF, INF, INF, 4},
{INF, INF, INF, INF, INF, INF},
{INF, INF, INF, INF, 2, INF}}; // 用一個全局二維數(shù)組存儲帶權有向圖的鄰接矩陣
void shortest_path(int start, int end);
void print_shortest_path(int* distance,int* path,int* used,int start,int end);
int main(){
int i;
char s1[3];
for(i=1;i<6;i++){
shortest_path(0, i);
}
return 0;
}
void shortest_path(int start, int end){ // 基于Dijkstra算法的最短路徑函數(shù)
int distance[N]; // 用于存放起始點到其余各點的最短距離
int path[N]; // 用于存放起始點到其余各點最短路徑的前一個頂點
int used[N] = { 0 }; // 用于標記該頂點是否已經(jīng)找到最短路徑
int i, j, min_node, min_dis, pass_flag = 0;
for(i = 0; i < N; i++){
distance[i] = adj_arr[start][i]; // 初始化距離數(shù)組
if(adj_arr[start][i] < INF){
path[i] = start; // 初始化路徑數(shù)組
}else{
path[i] = -1;
}
}
used[start] = 1;
path[start] = start;
for(i = 0; i < N; i++){
min_dis = INF;
for(j = 0; j < N; j++){
if(used[j] == 0 && distance[j] < min_dis){
min_node = j;
min_dis = distance[j];
pass_flag++; // 標記是否存在通路
}
}
if(pass_flag != 0){
used[min_node] = 1;
for(j = 0; j < N; j++){
if(used[j] == 0){
if(adj_arr[min_node][j] < INF && distance[min_node] + adj_arr[min_node][j] < distance[j]){
distance[j] = distance[min_node] + adj_arr[min_node][j];
path[j] = min_node;
}
}
}
}else{
printf("沒有通路!n");
return;
}
}
print_shortest_path(distance, path, used, start, end);
return;
}
void print_shortest_path(int* distance,int* path,int* used,int start,int end){ // 輸出最短距離并打印最短路徑
int i = 0, pre, inverse_path[N];
char s1[3],s2[3];
sprintf(s1, "V%d", (start+1));
sprintf(s2, "V%d", (end+1));
printf("從%s頂點到%s頂點的最短距離: %dn", s1, s2, distance[end]);
inverse_path[i] = end;
pre = path[end];
if(pre == -1){
printf("沒有通路!n");
}else{
while(pre != start){
inverse_path[++i] = pre;
pre = path[pre];
}
inverse_path[++i] = start;
printf("從%s頂點到%s頂點的最短路徑:n", s1, s2);
for(; i > 0; i--){
sprintf(s1, "V%d", (inverse_path[i]+1));
printf("%s -> ", s1);
}
sprintf(s1, "V%d", (inverse_path[i]+1));
printf("%sn", s1);
}
return;
}
四、求出最短路徑,要過程,用Dijkstra算法。。。
從v1開始遍歷
v2 = 2;
v3 = 5;
v2較小所以跳到v2
v3 = 4;
v4 = 6;
v5 = 8;
v3較小所以跳到v3
v4 = 5;
v6 = 7;
v4較小所以跳到v4
v6 = 6;
v7 = 9;
v6較小所以跳到v6
v7 = 8;
所以最后結果v1 -> v7最短路徑為v1->v2->v3->v4->v6->v7,最短路徑長度為8
以上就是關于如何求最短路徑相關問題的回答。希望能幫到你,如有更多相關問題,您也可以聯(lián)系我們的客服進行咨詢,客服也會為您講解更多精彩的知識和內(nèi)容。
推薦閱讀: