基于MATLAB求解最短路问题

相关主题
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

基于MATLAB求解最短路问题

1.引言

MATLAB和Mathematica、Maple并称为三大数学软件。它在数学类科技应用软件中在数值计算方面首屈一指。通过本学期的学习了解和上机实践,已经初步掌握使用MATLAB工具解决实际问题的能力。结合运筹学课程的学习,我考虑使用MATLAB求解最短路问题,而在所有求解最短路的方法中,Dijkstra算法是最为经典的一种,因此本文主要解决在MATLAB环境下使用Dijkstra算法求解最短路。

1.1 提出问题

设6个城市v1,v2,......,v6之间的一个公路网(图1)每条公路为图中的边,边上的权数表示该段公路的长度(单位:百公里),设你处在城市v1,那么从v1到v6应选择哪一路径使你的费用最省。

1.2 分析问题

这属于一个典型的求解最短路的问题,图中顶点代表六个城市,边上的权数表示该段公路的长度,题目所求为从v1到v6、的一条费用最省的路径,我们假设所需费用仅与路径长短有关,因此求费用最省的路径即求权值最小的路径。网络图中各权值均为正,可以使用Dijkstra算法。

1.3 数据整理

将网络图中各边的权作如下整理以方便程序运行

W(1,2)=5; W(2,1)=5;

W(1,3)=2; W(3,1)=2;

W(2,3)=1; W(3,2)=1;

W(2,4)=5; W(4,2)=5;

W(2,5)=5; W(5,2)=5;

W(3,4)=8; W(4,3)=8;

W(3,5)=10; W(5,3)=10;

W(4,5)=2; W(5,4)=2;

W(4,6)=5; W(6,4)=5;

W(5,6)=2; W(6,5)=2;

2.数学原理

2.1 Dijkstra算法介绍

Dijkstra 算法思想为:设G=(V,E)是一个带权有向图(也可以是无向图,无向图是有向图的特例),把图中顶点集合V分成两组:第一组为已求出最短路径的顶点集合(用S 表示,初始时S 中只有一个源点,以后每求得一条最短路径,就将其加入到集合S 中,直到全部顶点都加入到S 中,算法就结束了);第二组为其余未确定最短路径的顶点集合(用U 表示),按最短路径长度的递增次序依次把第二组的顶点加入S 中。在加入的过程中,总保持从源点v 到S 中各顶点的最短路径长度不大于从源点v 到U 中任何顶点的最短路径长度。此外,每个顶点对应一个距离,S 中的顶点的距离就是从v 到此顶点的最短路径长度,U中的顶点的距离,是从v 到此顶点只包括S 中的顶点为中间顶点的当前最短路径长度。其步骤主要有:

第一,初始时,S 只包含源点,即S={顶点},v 的距离为0。U 包含除v 外的其他顶点,U 中顶点u 距离为边上的权(若v 与u 有边)或(若u 不是v 的出边邻接点)。

第二,从U 中选取一个距离v 最小的顶点k,把k 加入S 中(该选定的距离就是v 到k 的最短路径长度)。

第三,以k 为新考虑的中间点,修改U 中各顶点的距离;若从源点v 到顶点u的距离(经过顶点k)比原来距离(不经过顶点k)短,则修改顶点u 的

距离值,修改后的距离值的顶点k 的距离加上边上的权。

第四,重复步骤第二步和第三步直到所有顶点都包含在S 中。

3.程序设计

function [c0,c,path0,path]=dijkstra(s,t,C,flag)

s=floor(s);

t=floor(t);

n=size(C,1);

label=ones(1,n)*inf;

label(s)=0;

S=[s];

Sbar=[1:s-1,s+1:n];

c0=0;

path=zeros(n,n);

path(:,1)=s;

c=ones(1,n)*inf;

parent=zeros(1,n);

i=1; % number of points in point set S.

while i

% for each point in Sbar, replace label(Sbar(j)) by

% min(label(Sbar(j)),label(S(k))+C(S(k),Sbar(j)))

for j=1:n-i

for k=1:i

if label(Sbar(j)) > label(S(k))+C(S(k),Sbar(j))

label(Sbar(j))=label(S(k))+C(S(k),Sbar(j));

parent(Sbar(j))=S(k);

end

end

end

% Find the minmal label(j), j \in Sbar.

temp=label(Sbar(1));

son=1;

for j=2:n-i

if label(Sbar(j))< temp

temp=label(Sbar(j));

son=j;

end

end

% update the point set S and Sbar

S=[S,Sbar(son)];

Sbar=[Sbar(1:son-1),Sbar(son+1:n-i)];

i=i+1;

% if flag==1, just output the shortest path between s and t.

if flag==1 && S(i)==t

son=t;

temp_path=[son];

if son~=s

while parent(son)~=s

son=parent(son);

temp_path=[temp_path,son];

end

temp_path=[temp_path,s];

end

temp_path=fliplr(temp_path);

m=size(temp_path,2);

path0(1:m)=temp_path;

c_temp=0;

for j=1:m-1

c_temp=c_temp+C(temp_path(j),temp_path(j+1));

end

c0=c_temp;

path(t,1:m)=path0;

c(t)=c0;

return

end

end

% Form the output results

for i=1:n

son=i;

temp_path=[son];

if son~=s

while parent(son)~=s

son=parent(son);

temp_path=[temp_path,son];

end

temp_path=[temp_path,s];

end

temp_path=fliplr(temp_path);

m=size(temp_path,2);

path(i,1:m)=temp_path;

c_temp=0;

for j=1:m-1

c_temp=c_temp+C(temp_path(j),temp_path(j+1));

end

c(i)=c_temp;

c0=c(t);

相关文档
最新文档