关键词不能为空

当前您在: 主页 > 英语 >

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最短路径算法的相关文章

  • 余华爱情经典语录,余华爱情句子

    余华的经典语录——余华《第七天》40、我不怕死,一点都不怕,只怕再也不能看见你——余华《第七天》4可是我再也没遇到一个像福贵这样令我难忘的人了,对自己的经历如此清楚,

    语文
  • 心情低落的图片压抑,心情低落的图片发朋友圈

    心情压抑的图片(心太累没人理解的说说带图片)1、有时候很想找个人倾诉一下,却又不知从何说起,最终是什么也不说,只想快点睡过去,告诉自己,明天就好了。有时候,突然会觉得

    语文
  • 经典古训100句图片大全,古训名言警句

    古代经典励志名言100句译:好的药物味苦但对治病有利;忠言劝诫的话听起来不顺耳却对人的行为有利。3良言一句三冬暖,恶语伤人六月寒。喷泉的高度不会超过它的源头;一个人的事

    语文
  • 关于青春奋斗的名人名言鲁迅,关于青年奋斗的名言鲁迅

    鲁迅名言名句大全励志1、世上本没有路,走的人多了自然便成了路。下面是我整理的鲁迅先生的名言名句大全,希望对你有所帮助!当生存时,还是将遭践踏,将遭删刈,直至于死亡而

    语文
  • 三国群英单机版手游礼包码,三国群英手机单机版攻略

    三国群英传7五神兽洞有什么用那是多一个武将技能。青龙飞升召唤出东方的守护兽,神兽之一的青龙。玄武怒流召唤出北方的守护兽,神兽之一的玄武。白虎傲啸召唤出西方的守护兽,

    语文
  • 不收费的情感挽回专家电话,情感挽回免费咨询

    免费的情感挽回机构(揭秘情感挽回机构骗局)1、牛牛(化名)向上海市公安局金山分局报案,称自己为了挽回与女友的感情,被一家名为“实花教育咨询”的情感咨询机构诈骗4万余元。

    语文