最短路徑算法 (一)——求出路徑長度 (*^__^*) 嘻嘻……
阿新 • • 發佈:2017-11-01
沒有 str -1 man 最大 連線 問題 輸入 sha
【問題描述】:
平面上有n(n<=100)個點,每個點的坐標均在-10000~10000之間。
其中的一些點之間有連線。若有連線,則表示可以從一個點到達另一個點,即兩點之間有通路,通路的距離為兩點之間的直線距離。
現在的任務是找出從一個點到另一個點的最短路徑。
【輸入格式】:
第1行:整數n
第2行到第n+1:每行兩個整數x y,描述了一個點的坐標。
第n+2行:一個整數m,表示圖中連線的個數
此後m行:每行描述一條連線,由兩個整數i和j構成,表示第i個點和第j個點之間有連線
最後一行:兩個整數s t,分別表示源點和目標點
【輸出格式】:
僅一行,一個實數(保留兩位小數),表示從s到t的最短路徑長度
【輸入樣例】:
5
0 0
2 0
2 2
3 1
5
1 2
1 3
1 4
2 5
3 5
1 5
【輸出樣例】:
3.41
1.Floyed-Warshall 算法 O(N^3)
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 using namespacestd; 6 int a[101][3]; 7 double f[101][101]; 8 int n,m,x,y,s,e,k; 9 int maxx=0X7f; 10 int main() 11 { 12 int i,j; 13 scanf("%d",&n); 14 for(i=1;i<=n;i++) 15 { 16 cin>>a[i][1]>>a[i][2]; 17 } 18 scanf("%d",&m); 19 memset(f,maxx,sizeof(f)); 20 for(i=1;i<=m;i++) 21 { 22 cin>>x>>y; 23 f[x][y]=f[y][x]=sqrt(pow(double(a[x][1]-a[y][1]),2)+pow(double(a[x][2]-a[y][2]),2)); 24 } 25 scanf("%d%d",&s,&e); 26 27 /*最外層的k是枚舉位於起點和終點中的跳板,貪心的正確性必須得到保證, 28 而這個保證在於,再求f[i][j]時,f[i][k]和f[k][j]若可達(一般來說把不可達設置為無窮大), 29 必須為最優值(即最短距離).其中k作為中間點,我們是把它當作階段,而起點,終點的i,j我們稱為狀態(參考動態規劃)—— 30 第k次循環後,保證每個點到頂點k的距離,要麽不可達,要麽是最短距離,大前提是距離上除了起點和終點只有1~k-1這k-1個點。 31 當我們的k值從1枚舉到n(假設頂點下標從1開始編號),那麽我們獲得的最短路徑上允許出現的點的編號,就從1增加到n,當n被允許加入路徑中, 32 那麽這個最短路徑問題就得到解決。因為所有的頂點在最短路徑的位置都被考慮了。*/ 33 34 for(k=1;k<=n;k++) 35 for(i=1;i<=n;i++) 36 for(j=1;j<=n;j++) 37 if((i!=j)&&(i!=k)&&(j!=k) &&f[i][k]+f[k][j]<f[i][j]) 38 f[i][j]=f[i][k]+f[k][j]; 39 printf("%.2lf",f[s][e]); 40 return 0; 41 }
2.Dijkstrs 算法 O(N^2)
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 using namespace std; 6 bool b[101]; 7 double f[101][101]; 8 int a[101][3]; 9 double c[101]; 10 double maxx=1e30; 11 int main() 12 { 13 int i,n,j,k,x,y,s,e,m; 14 cin>>n; 15 for(i=1;i<=n;i++)//讀入n個點的坐標 16 cin>>a[i][1]>>a[i][2]; 17 18 for(i=1;i<=n;i++)//f數組初始值最大化 19 for(j=1;j<=n;j++) 20 f[i][j]=maxx; 21 cin>>m; 22 for(i=1;i<=m;i++) 23 { 24 cin>>x>>y; 25 f[x][y]=f[y][x]=sqrt(pow(a[x][1]-a[y][1],2)+pow(a[x][2]-a[y][2],2));//求兩個點間的距離(兩點間的坐標距離公式) 26 27 } 28 cin>>s>>e; 29 30 for(i=1;i<=n;i++)//每個點到起點的最短路徑最開始賦值為與起點的坐標距離 31 c[i]=f[s][i]; 32 33 b[s]=true; 34 c[s]=0; 35 for(i=1;i<=n-1;i++)//查找可以更新的節點 36 { 37 double minil=maxx; 38 k=0; 39 for(j=1;j<=n;j++) //在沒有被訪問過的點中,找一點k使得才c[k]值最小 40 if((!b[j]) && c[j]<minil) 41 { 42 minil=c[j]; 43 k=j; 44 } 45 if(k==0) break;//所有的點都被訪問就退出循環 46 47 b[k]=true; //把點k標記為已確定的最短路徑 48 49 for(j=1;j<=n;j++) //對與k相連的點的最短路徑進行更新 50 if(c[k]+f[k][j]<c[j]) 51 c[j]=c[k]+f[k][j]; 52 53 } 54 printf("%.2f\n",c[e]); 55 return 0; 56 57 58 }
3.Bellman-Ford 算法 O(NE) //福特算法
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 using namespace std; 6 int a[101][3]; 7 double dis[1001],w[1001]; 8 int f[103][3]; 9 int maxx=0X7fffffff/3; 10 int main() 11 { 12 int s,t,i,j,k,n,m,x,y; 13 cin>>n; 14 for(i=1;i<=n;i++) 15 scanf("%d%d",&a[i][1],&a[i][2]); 16 cin>>m; 17 for(i=1;i<=m;i++) 18 { 19 dis[i]=maxx; 20 f[i][1]=f[i][2]=maxx; 21 } 22 for(i=1;i<=m;i++) 23 { 24 scanf("%d%d",&x,&y); 25 f[i][1]=x; 26 f[i][2]=y; 27 w[i]=sqrt(pow(a[x][1]-a[y][1],2)+pow(a[x][2]-a[y][2],2)); 28 29 } 30 cin>>s>>t; 31 dis[s]=0; 32 for(i=1;i<=n;i++) 33 for(j=1;j<=m;j++) 34 { 35 if(dis[f[j][1]]+w[j]<dis[f[j][2]]) dis[f[j][2]]=dis[f[j][1]]+w[j]; 36 if(dis[f[j][2]]+w[j]<dis[f[j][1]]) dis[f[j][1]]=dis[f[j][2]]+w[j]; 37 } 38 printf("%.2f",dis[t]); 39 return 0; 40 41 }
最短路徑算法 (一)——求出路徑長度 (*^__^*) 嘻嘻……