1. 程式人生 > >12.帶權有向圖中任意兩點間的最短路徑

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]);     } } } } 輸出結果跟上面一樣的!