1. 程式人生 > >最短路徑算法 (一)——求出路徑長度 (*^__^*) 嘻嘻……

最短路徑算法 (一)——求出路徑長度 (*^__^*) 嘻嘻……

沒有 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 namespace
std; 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 } 

最短路徑算法 (一)——求出路徑長度 (*^__^*) 嘻嘻……