关键词不能为空

当前您在: 主页 > 英语 >

Floyd最短路径算法

作者:高考题库网
来源:https://www.bjmy2z.cn/gaokao
2021-02-01 21:47
tags:

-

2021年2月1日发(作者:加斯科)











Floyd


最短路径算法



2006-10-20, by leon_jlu




在图论中经常会遇到这样的问题,在一个有向图里,求出 任意两个节点之间


的最短距离。


我们在离散数学、


数据结构课上都遇到过这个问题,


在计算机网络


里介 绍网络层的时候好像也遇到过这个问题,记不请了


...


但是 书本上一律采取


的是


Dijkstra


算法,通过


Dijkstra


算法可以求出单源最短路径,然后 逐个节点利



Dijkstra


算法就 可以了。


不过在这里想换换口味,


采取


Robert Floyd


提出的算


法来解决这个问题。下面让 我们先把问题稍微的形式化一下:






如果有一个矩阵


D=[d(ij)]


,其中


d(ij)>0


表示


i


城市到


j


城市的距离。若


i



j


之间无路可通,那么


d(ij)


就是 无穷大。又有


d(ii)=0


。编写一个程序,通过

< p>
这个距离矩阵


D


,把任意两个城市之间的最短与其 行径的路径找出来。





我们可以将问题分解,先找出最短的距离,然后在考虑如何找出对应的行进

< br>路线。


如何找出最短路径呢,


这里还是用到动态规划的知 识,


对于任何一个城市


而言,


i



j


的最短距离不外乎存在经过


i



j


之间的


k


和不经过


k


两种可能,所


以可以令


k=1


2



3



...



n(n


是城市的数目


)


,在检查


d(ij)



d(ik)+d(kj)


的值;


在此


d(ik)



d(kj)


分别是目前为止所知道的


i



k



k



j


的最短距离,因此


d(ik)+d(kj)

就是


i



j


经过


k


的最短距离。


所以,


若有


d(ij)>d(ik)+d(kj)


,< /p>


就表示



i


出发 经过


k


再到


j


的距离要比原来的


i



j


距离短,自然把


i



j



d(ij)


重写



d(ik)+d(kj)


,每当一个


k


查完了,


d(ij)


就是目前的


i



j


的最短距离 。重复这


一过程,


最后当查完所有的


k


时,


d(ij)


里面存放的就是


i



j


之间的最短距 离了。


所以我们就可以用三个


for


循 环把问题搞定了,但是有一个问题需要注意,那就



for


循环的嵌套的顺序:我们可能随手就会写出这样的程序,但是仔细考虑的

话,会发现是有问题的。











for(int i=0; i











for(int j=0; j












for(int k=0; k








问题出在我们太早的把


i-k- j


的距离确定下来了,假设一旦找到了


i-p-j


最短


的距离后,


i



j


就相当处理完了,以后不会在改变了,一旦以后有使


i



j


的更

< br>短的距离时也不能再去更新了,


所以结果一定是不对的。


所以应当象下面一样来


写程序:










for(int k=0; k












for(int j=0; j







这样作的意义在于固定了


k



把所有


i



j


而经过


k


的距离找 出来,


然后象开


头所提到的那样进行比较和重写,因为


k


是在最外层的,所以会把所有的


i

< p>


j


都处理完后,


才会移 动到下一个


k



这样就不会有问题了,


看来多层循环的时候,


我们一定要当心,否则很容易就弄错了。





接下来就要看一看如何找出最短路径所行经的城市了,


这里要用到另一个矩



P


,它的定义是这样的:


p(ij)


的值如果为


p


,就表示


i



j


的最短行经 为


i->...->p->j


,也就是说


p



i



j


的最短行径中的


j


之前的最后一个城市 。


P



阵的初值为

p(ij)=i


。有了这个矩阵之后,要找最短路径就轻而易举了。对于

< p>
i



j


而言找出


p(ij)



令为


p< /p>



就知道了路径


i->...->p-> j



再去找


p(ip)



如果值为


q



i



p


的最短路径为


i->...->q->p


;再去找


p(iq )


,如果值为


r


i



q


的最短路径



i->...->r->q



所以一再反复,


到了某个


p(it)


的值为


i


时,


就表示

< br>i



t


的最短

< br>路径为


i->t


,就会的到答案了,

i



j


的最短行径为


i->t->...->q->p->j


。因为上


述 的算法是从终点到起点的顺序找出来的,所以输出的时候要把它倒过来。





但是,如何动态的回填


P


矩阵的值呢?回想一下,当


d(ij)> d(ik)+d(kj)


时,


就要让


i



j


的最短路径改为走


i->...->k->...->j


这一条路,但是


d(kj)


的值是已


知的,换句话说,就是

k->...->j


这条路是已知的,所以


k->...- >j


这条路上


j


上一个城市


(



p(kj))


也是已知的,


当然,


因为要改走

< p>
i->...->k->...->j


这一条路,


j


的上一个城市正好是


p(kj)


。所 以一旦发现


d(ij)>d(ik)+d(kj)


,就把


p(kj)


存入


p(ij)

< br>。




下面是具体的


C


代码:




#include








#include







#include







#define


MAXSIZE


20






void floyd(int [][MAXSIZE], int [][MAXSIZE], int);



void display_path(int [][MAXSIZE], int [][MAXSIZE], int);



void reverse(int [], int);



void readin(int [][MAXSIZE], int *);




#define


MAXSUM(a, b)


(((a) != INT_MAX && (b) != INT_MAX) ?










((a) + (b)) : INT_MAX)




void floyd(int dist[][MAXSIZE], int path[][MAXSIZE], int n)



{





int i, j, k;





for (i = 0; i < n; i++)





for (j = 0; j < n; j++)







path


[j] = i;





for (k = 0; k < n; k++)





for (i = 0; i < n; i++)








for (j = 0; j < n; j++)








if (dist[j] > MAXSUM(dist[k], dist[k][j]))


{











path[j] = path[k][j];












dist[j] = MAXSUM(dist[k], dist[k][j]);








}



}




void display_path(int dist[][MAXSIZE], int path[][MAXSIZE], int n)



{





int *chain;





int count;





int i, j, k;





printf(


Dist



ath





printf(





chain = (int *) malloc(sizeof(int)*n);





for (i = 0; i < n; i++)






for (j = 0; j < n; j++)





{







if (i != j)







{








printf(










if (dist[j] == INT_MAX)












printf(











else








{











printf(













count = 0;












k = j;











do











{











k = chain[count++] = path[k];











} while (i != k);











reverse(chain, count);












printf(












for (k = 1; k < count; k++)












printf(











printf(








}







}





}





free(chain);








}




#define SWAP(a, b) { temp = a; a = b; b = temp; }




void reverse(int x[], int n)



{





int i, j, temp;
















for (i = 0, j = n-1; i < j; i++, j--)






SWAP(x, x[j]);



}




void readin(int dist[][MAXSIZE], int *number)



{





int origin, dest, length, n;





int i, j;





char line[100];





gets(line);









sscanf(line,





*number = n;





for (i = 0; i < n; i++)






{





for (j = 0; j < n; j++)








dist[j] = INT_MAX;





dist = 0;






}





gets(line);









sscanf(line,





while (origin != 0 && dest != 0 && length != 0)





{






dist[origin-1][dest-1] = length;






gets(line);









sscanf(line,





}



}




测试程序如下所示:




int main(void)



{





int dist[MAXSIZE][MAXSIZE];





int path[MAXSIZE][MAXSIZE];





int n;





printf(





printf(





readin(dist, &n);





floyd(dist, path, n);





display_path(dist, path, n);





getchar();



}




其中


readin


函数规定了输入的格式,


第一列是指出有多少个 城市;


第二列以


后每行三个数;


第一个 和第二个是一条路径的起点和终点,


第三个数是路径的长


度,最 后以三个


0


作为输入结束条件。下面是一个输入的例子:







Input the path information:






--------------------------------------






4






1





2





5


2





1





50






2





3





15






2





4





5






3





1





30






3





4





15






4





1





15






4





3





5






0





0





0




对应的输出结果为:




Origin->Dest



Dist





Path


----------------------------------------------




1->2






5




1->2




1->3





15





1->2->4->3




1->4





10





1->2->4




2->1





20





2->4->1




2->3





10





2->4->3




2->4






5




2->4




3->1





30





3->1




3->2





35





3->1->2




3->4





15





3->4




4->1





15





4->1




4->2





20





4->1->2




4->3






5




4->3



Dijkstra


算法是由荷兰计算 机科学家艾兹格


?


迪科斯彻发现的。


算 法解决的是有向


图中最短路径问题。




举例来说,


如果图中的顶点表示城市,


而边上的权重表示著城市间开车行经的距


离。



Dijkstra


算法可以用来找到两个城市之间的最短路径。




Dijkstra


算法的 输入包含了一个有权重的有向图


G



以 及


G


中的一个来源顶点


S




我们以


V


表示


G


中所有顶点的集合。



每一个图中的边,都是两个顶点所形成的


有序元素对。


(u,v)


表示从顶点


u



v


有路径相连。



我们以


E


所有边的集合,而


边 的权重则由权重函数


w: E




[0, ∞]


定义。



因此,


w(u,v)


就是从顶点


u


到顶



v


的非负花费值


(cost)




边的花费可以想像成两个顶点之间的距离。


任两点间

< br>路径的花费值,就是该路径上所有边的花费值总和。



已 知有


V


中有顶点


s


t



Dijkstra


算法可以找到


s



t< /p>


的最低花费路径


(i.e.


最短路径


)




这个算法也可以


在一个图中,找到从一个顶点

< br>s


到任何其他顶点的最短路径。




算法描述



这个算法是通过为每个顶点


v


保留目前为止所找到的从


s



v


的最短路径来工 作


的。初始时,源点


s


的路径长度值被 赋为


0



d[s]=0


),



同时把所有其他顶点


的 路径长度设为无穷大,即表示我们不知道任何通向这些顶点的路径(对于


V


中所有顶点


v



s



d[v]= ∞


)。当算法结束时,


d[v]


中储存的便是从


s


v



最短路径,或者如果路径不 存在的话是无穷大。



Dijstra


算法的基础操作是边的


拓展:


如果存在一条从

< br>u



v


的边,

< br>那么从


s



u

< br>的最短路径可以通过将边


(u,v)


添加到尾部来拓展一 条从


s



v


的 路径。这条路径的长度是


d+w(u,v)


。如果这

< p>
个值比目前已知的


d[v]


的值要小,

< p>
我们可以用新值来替代当前


d[v]


中的值。


拓展


边的操作一直执行到所有的


d[v]< /p>


都代表从


s



v


最短路径的花费。


这个算法经过


组织因 而当


d


达到它最终的值的时候没条边


( u,v)


都只被拓展一次。



算法维护 两个顶点集


S



Q

。集合


S


保留了我们已知的所有


d [v]


的值已经是最


短路径的值顶点,而集合

< br>Q


则保留其他所有顶点。集合


S


初始状态为空,而后


每一步都有一个顶点从


Q

< br>移动到


S


。这个被选择的顶点是


Q


中拥有最小的


d


< br>的顶点。


当一个顶点


u



Q


中转移到了


S


中,


算法对每条外接边


(u,v)


进行拓展 。




在下面的算法中


,u:=Extract_Min(Q)


在在顶点集


Q


中搜索有最小的


d


值的顶点

< p>
u



这个顶点被从集合


Q


中删除并返回给用户。



1 function Dijkstra(G, w, s)


2


for each vertex v in V[G]









//


初始化



3




d[v] := infinity


4




previous[v] := undefined


5


d[s] := 0


6


S := empty set


7


Q := set of all vertices


8


while Q is not an empty set









// Dijstra


算法主体



9




u := Extract_Min(Q)


10




S := S union {u}


11




for each edge (u,v) outgoing from u


12







if d[v] > d + w(u,v)






//


拓展边


(u,v)


13









d[v] := d + w(u,v)


14









previous[v] := u


如果我们只对在


s



t


之间寻找一条最短路径的话,

< p>
我们可以在第


9


行添加条件


如果满足


u=t


的话终止程序。


< /p>


现在我们可以通过迭代来回溯出


s



t


的最短路径



1 S := empty sequence



2 u := t


3 while defined u
















4




insert u to the beginning of S


5




u := previous


现在序列


S


就是从


s



t


的最短路径的顶点集


.


本人自己 写的蚁群算法。完全能


够实现功能,就是收敛速度感觉有点慢。



%


function


[R_bes t,L_best,L_ave,Shortest_Route,Shortest_Length]=ACO (C,D,s,e,NC_ma


x,m,Alpha,Beta,Rho,Q)


%


function


[Short est_Route,Shortest_Length]=ACOR(C,D,s,e,NC_max,m,A lpha,Beta,Rho,


Q)


%%========= ===================================


==== =========================


%% ACO.m


%% Ant Colony Optimization Algorithm for Road Select Problem


%% LiLixin,ShenYang Insitute of Aeronautical engineering ,ShenYang,China


%% Email:myassist@


%% All rights reserved


%%------------------------------------- ------------------------------------


%%


主要符号说明



%% C n


个城市的坐标,



2


的矩阵



%% D


道路连通加权矩阵



%% s


起点



%% e


终点



%% NC_max


最大迭代次数



%% m


蚂蚁个数



%% Alpha


表征信息素重要程度的参数



%% Beta


表征启发式因子重要程度的参数



%% Rho


信息素蒸发系数



%% Q


信息素增加强度系数



%% R_best


各代最佳路线



%% L_best


各代最佳路线的长度



%%===== =======================================


=============================


%



clc


clear


%


设置初始参数如下:


< p>
m=10;Alpha=1;Beta=5;Rho=0.1;NC_max=100;Q=100 ;


%


设定起始点



s=1;e=50;


% 31


城市坐标为:



C=[601.6





971.7


988.8





482.6


54.4





549.6


95.4





868


529.1





429.5


982





350.5


654.3





23.2


738.1





372


538.9





593.7


560.1





850.3


229.2





805.9


411.2





710


83.2





706.2


937.4





800.5


11.9





994.4


694.1





809.1


795.4





758.8


338.9





148.1


955.8





643.8


345.7





726.2


550.3





349.6


183.7





935.1


640





544


854.6





842.4


199.3





547.9


434.1





921.4


405.5





624.2


272.3





998.1


772





24.4


385.2





327.4


320.3





410.4


890





90


810





580


180





80


185





300


950





200


850





258.6


50





450


150





402


345





900


450





800


621





700


564.3





180


80.5





280


750





950


450





500


300





50


900





530


300





520


152





189.6


];


D=[0





0





0





0





0





0





0





0





0





76.92





0





0





0





0





0





230.95





0






0





0





0





0





0





0





0





0





76.8


94





0





0





0





0





0





0





0





0






0





0





0





0





0





0





0





0





0





0





157.34





0





0





0





0





0


0





0





0





0





0





140.78





0





325.12





0





0





0





0





0





0





0





0





0






0





155.71





0





0





0





0





0





0





0






0





0





0





0





0





0





0





0





0






0





0





0





0





0





0





0





0





0






0





0





0





76.913





0





0


0





0





0





0





0





0





0





0





0





0





0





0





74.247





0





0





0





0





0






0





0





0





0





0





0





55.603





0






0





0





0





0





0





0





0





0





0





0





0





76.921





0





0





0





0





0





0






0





0





0





0





0





0


0





0





0





0





0





0





0





0





0





0





147.8





0





76.551





0





76.908





0





0






0





0





0





0





79.548





0





0





0






0





0





0





0





0





0





0





0





0






0





0





0





0





0





0





0





0





0






0





0





0





0





0





0





0


0





0





0





0





0





0





0





0





0





0





0





0





0





0





0





0





0





0





0





0





84.189





0





0





0





0





0





0






0





0





166.74





0





0





0





0





0






0





0





0





0





0





0





0





0





0





0





76.915





0





0





0





0


0





140.78





0





0





0





0





0





211.43





0





0





0





0





0





0





0





0





0






0





0





0





0





0





0





0





0





0





0





0





0





0





0





0





0





0





0





76.91





0





0





0





0





0





0





0





0





0





0





0





0





0





0


0





0





0





0





0





0





0





205.65





0






0





0





0





0





0





0





0





0





0






0





0





0





0





0





0





0





0





0






0





76.91



0





0





0





0





0





0





0





0





0






0





0





0





0





76.901





0





0





0






156.87





0





0





0


0





325.12





0





0





0





211.43





205.65





0






0





0





0





0





0





0





0





0





0






0





0





0





79.979





0





258.19





0





0





0





0





0





0





0





0





0





0





0





0





0





73.841





0





0





0





0





0






0





0





0





0





0





0





0





0


0





0





0





0





0





0





0





0





0





0





0





76.898





0





0





0





0





0





0






0





0





0





0





79.382





0





0





0






75.438





0





0





0





0





0





0





0





0






0





0





0





0





0





0





0





0





0






0





0





0





0





0





0


76.92





0





0





0





0





0





0





0





0





0





0





0





0





0





0





80.01





0





0






0





0





0





0





0





0





0





79.064





0





0





0





0





0





0





0





0





0






0





0





0





0





0





76.919





0





0





0





0





0





0





0





0





0


0





0





0





147.8





0





0





0





0





0





0





0





0





147.14





0





0





0





0





0





0





163.89





0





60.464





0





0





0





0





0





151.26





0





0





0





0





0





0

-


-


-


-


-


-


-


-



本文更新与2021-02-01 21:47,由作者提供,不代表本网站立场,转载请注明出处:https://www.bjmy2z.cn/gaokao/595321.html

Floyd最短路径算法的相关文章

  • 爱心与尊严的高中作文题库

    1.关于爱心和尊严的作文八百字 我们不必怀疑富翁的捐助,毕竟普施爱心,善莫大焉,它是一 种美;我们也不必指责苛求受捐者的冷漠的拒绝,因为人总是有尊 严的,这也是一种美。

    小学作文
  • 爱心与尊严高中作文题库

    1.关于爱心和尊严的作文八百字 我们不必怀疑富翁的捐助,毕竟普施爱心,善莫大焉,它是一 种美;我们也不必指责苛求受捐者的冷漠的拒绝,因为人总是有尊 严的,这也是一种美。

    小学作文
  • 爱心与尊重的作文题库

    1.作文关爱与尊重议论文 如果说没有爱就没有教育的话,那么离开了尊重同样也谈不上教育。 因为每一位孩子都渴望得到他人的尊重,尤其是教师的尊重。可是在现实生活中,不时会有

    小学作文
  • 爱心责任100字作文题库

    1.有关爱心,坚持,责任的作文题库各三个 一则150字左右 (要事例) “胜不骄,败不馁”这句话我常听外婆说起。 这句名言的意思是说胜利了抄不骄傲,失败了不气馁。我真正体会到它

    小学作文
  • 爱心责任心的作文题库

    1.有关爱心,坚持,责任的作文题库各三个 一则150字左右 (要事例) “胜不骄,败不馁”这句话我常听外婆说起。 这句名言的意思是说胜利了抄不骄傲,失败了不气馁。我真正体会到它

    小学作文
  • 爱心责任作文题库

    1.有关爱心,坚持,责任的作文题库各三个 一则150字左右 (要事例) “胜不骄,败不馁”这句话我常听外婆说起。 这句名言的意思是说胜利了抄不骄傲,失败了不气馁。我真正体会到它

    小学作文