12.帶權有向圖中任意兩點間的最短路徑
其實它的程式碼理解起來真的挺難的我覺得!!!
昨天看了一下午感覺晦澀難懂,還是matlab好用,直接呼叫函式就可以了!!!
不過這裡還是得跟大家介紹一下:
1.問題的理解:
像這種帶權的有向圖,每一行都表示該行標號對應列標號的有向權值,本身到本身的數值為0,沒辦法到達的數值為∞
2.最優子結構
i,j是圖裡面的兩個不同頂點,設p為從i到j的不經過{k+1,k+2,...n}點的最短路徑
(1)若p不經過頂點k,則p也是從i到達j其間不經過{k,k+1,k+2...n}的最短路徑
(2)若p經過頂點k,我們把前半段從i到k記為p1,後半段從k到j記做p2,則p1是從i到k不經過{k,k+1,...n}的最短路徑,p2是從k到j的其間不經過{k,k+1,k+2...n}的最短路徑
演算法虛擬碼:
FLOYD-WARSHALL(w)
1. for i<-1 to n
2. do for j<-1 to n
3. do if i=j or w[i,j]=∞
4. then π[i,j]<-NIL
5. else π[i,j]<-i
6. D<-w
7. for k<-1 to n
8. do for i<- 1 to n
9. do for j<-1 to n
10. if D[i,j]>D[i,k]+D[k,j]
11. then D[i,j]<-D[i,k]+D[k,j]
12. π[i,j]<-π[k,j]
13. return D,π
(吐槽一下,這裡的D其實就是每行標號到每列標號的最短距離,後期程式出來後還是很漂亮的,然後這裡的π我就不知道什麼鬼了,索性就不管他啦,哈哈!!)
PRINT-ALL-PAIRS-SHORTEST -PATHS(π,i,j)
1. if i=j
2. then print i
3. else if π[i,j]=NIL
4. then print"no path from " i “to” j "exists"
5. else PRINT-ALL-PAIRS-SHORTEST-PATHS(π,i,π[i,j])
6. print j
C++:
floyd.h
#define _floyd_h #include<string.h> #include<float.h> #include<stdio.h> #include"pair.h" #include<malloc.h> pair floydwarshall(double* w,int n){ double *d=(double*)malloc(n*n*sizeof(double)); int i,j,k,*pi=(int*)malloc(n*n*sizeof(int)); for(i=0;i<n;i++) for(j=0;j<n;j++) if(j==i||w[i*n+j]>=DBL_MAX) pi[i*n+j]=-1; else pi[i*n+j]=i; memcpy(d,w,n*n*sizeof(double)); for(k=1;k<=n;k++) for(i=0;i<n;i++) for(j=0;j<n;j++) if(d[i*n+j]>d[i*n+k-1]+d[(k-1)*n+j]){ d[i*n+j]=d[i*n+k-1]+d[(k-1)*n+j]; pi[i*n+j]=pi[(k-1)*n+j]; } return make_pair(d,pi); } void printallpairsshotestpath(int *pi,int n,int i,int j){ if(i==j){ printf("%d ",i+1); return; } if(pi[i*n+j]==-1) printf("no path from %d to %d exists.\n",i+1,j+1); else{ printallpairsshotestpath(pi,n,i,pi[i*n+j]); printf("%d ",j+1); } }
main.cpp
#include<stdlib.h> #include"floyd.h" int main(){ double w[]={0,3,8,DBL_MAX,-4, DBL_MAX,0,DBL_MAX,1,7, DBL_MAX,4,0,DBL_MAX,DBL_MAX, 2,DBL_MAX,-5,0,DBL_MAX, DBL_MAX,DBL_MAX,DBL_MAX,6,0},*d; int i,j,k,*pi,n=5; pair r; r=floydwarshall(w,n); d=(double*)r.first; pi=(int*)r.second; for(i=0;i<n;i++){ for(j=0;j<n;j++){ printallpairsshotestpath(pi,n,i,j); printf(":%1.1f\n",d[i*n+j]); } } free(d); free(pi); }
輸出結果:
JAVA:
Floyd.java
package Jamin; import java.util.Arrays; public class Floyd { public static Pair floydwarshall(double[][] w) { int n=w.length,i,j,k; double[][] d=new double[n][n]; int[][] pi=new int[n][n]; d=Arrays.copyOf(w,n); for(i=0;i<n;i++) for(j=0;j<n;j++) if(j==i||w[i][j]>=Double.MAX_VALUE) pi[i][j]=-1; else pi[i][j]=i; for(k=1;k<=n;k++) for(i=0;i<n;i++) for(j=0;j<n;j++) if(d[i][j]>d[i][k-1]+d[k-1][j]) { d[i][j]=d[i][k-1]+d[k-1][j]; pi[i][j]=pi[k-1][j]; } return Pair.make(d, pi); } public static void printallpairsshotestpath(int[][] pi,int i,int j) { int n=pi.length; if(i==j) { System.out.print((i+1)+" "); return; } if(pi[i][j]==-1) System.out.println("no path from " +(i+1)+"to "+(j+1)+"exists."); else { printallpairsshotestpath(pi,i,pi[i][j]); System.out.print((j+1)+" "); } } }
Test.java
package Jamin;
public class Test {
public static void main(String[] args) { // TODO Auto-generated method stub double[][] w= {{0.0,3.0,8.0,Double.MAX_VALUE,-4.0}, {Double.MAX_VALUE,0.0,Double.MAX_VALUE,1.0,7.0}, {Double.MAX_VALUE,4.0,0.0,Double.MAX_VALUE,Double.MAX_VALUE}, {2.0,Double.MAX_VALUE,-5.0,0.0,Double.MAX_VALUE}, {Double.MAX_VALUE,Double.MAX_VALUE,Double.MAX_VALUE,6.0,0.0} },d; int n=5,i,j,k; int[][] pi; Pair r; r=Floyd.floydwarshall(w); d=(double[][])r.first; pi=(int[][])r.second; for(i=0;i<n;i++) { for(j=0;j<n;j++) { Floyd.printallpairsshotestpath(pi, i, j); System.out.println(":"+d[i][j]); } } } } 輸出結果跟上面一樣的!