注明:本文根据数学建模BOOM网课简单整理,自用
❑ 基本概念
❑ 单源最短路径简单例子
• 法外狂徒张三和其他四个富豪分别住在5个城市
• 由于疫情,有些城市间只允许单向前往,或往返路径长度不同
• 5个城市之间不同路径的长度如图所示
• 张三打算到李四家行窃,如何以最短的路程到达李四家?
![](https://img-blog.csdnimg.cn/img_convert/f974bb4aa478865283dab4f427fad3fa.png)
❑ 单源最短路径:从图中某个顶点出发,到达另一个顶点所经过的边的权重之和最小的一条路径
• 本例子中的“路径长度”就是指真实的路径距离
• 若题目改为:每条路径的成本(过路费+燃油费)不同,如何以最少的成本到达李四家?
• 那么最短路径中的“路径长度”概念即为经过的路径消耗的总费用
❑ 边带有方向的图是有向图,否则为无向图
• 本题为有向图是因为题目要求“有些城市间只允许单向前往,或往返路径长度不同”
• 再次强调,权重表现的是“路径长度”,画出来是直线相连,并不代表现实中就是直线!
❑ 最短路径基本性质:最短路径上的任一子路径也是最短路径(计算机同学在数据结构中会学到)(贪心算法和动态规划的基础)
❑ 常用算法
• Dijkstra算法(迪杰斯特拉算法),基于贪心思想(百度上很多可以直接复制粘贴)
• Floyd算法,求出所有顶点对之间的最短路径,时间复杂度高
❑ 基本方法:调用MATLAB的shortestpath函数
• 根据题目画出图、写出邻接矩阵,调用函数即可
• shortestpath函数求两个单一节点之间的最短路径
❑ 对于做数模来说,掌握MATLAB函数求解即可
❑ 适用赛题
❑ 货物运输类问题
• 公路运输/铁路运输的路线固定,距离已知,每条路径耗费的费用已知
• 设计从某点出发,到达终点的运输路径,使总费用/路径最小
❑ 设备更新问题
• 购置新设备需要一笔费用,继续使用旧设备也需要支付维修费用且逐年增大
• 在一定年限内,如何安排购置新设备和使用旧设备,使总支付费用最小
❑ 典型特征
• 从某个“起点”到某个“终点”,即始终围绕 “起点到终点”的“总路径”求最优
• 这一点可以在看完最小生成树后思考两者的区别和联系
❑ 注意事项
• 图论解决的问题大部分是求最优解,常常与规划类模型结合
• 一般涉及已知点到点之间的路径/费用等,能作出图,即可用图论的算法求解
❑ 典型例题与原理讲解
❑先以简单例子讲解原理,后面讲解更复杂的例题的建模与求解
❑ Dijkstra算法求解单源最短路径的原理:贪心算法(可以求得起点到任意一点的最短路径)
• 集合S为已确定最短路径的点,集合Q为剩余顶点。初始时,集合S只有源点(起点)
• Q中每一个顶点,若源点可经过S中的点到达该点则为可行路径,更新该点的最短可行路径
• 从上一步所有最短可行路径中选取最短的路径,把对应顶点加入S
• 不断重复前两步,直到所有顶点都在S内或剩余顶点不存在可行路径为止
![](https://img-blog.csdnimg.cn/img_convert/c80a77b34f69c35f81c61b24284d1aca.png)
❑典型例题
❑ 设备更新问题
• 某企业使用一台设备,每年年初需要决定是购置新的,还是继续使用旧的
• 购置新的就需要一定的购置费用,使用旧的需要支付逐年增加的维修费用
• 五年内该设备在每年年初的价格,和使用不同时间(年)的设备需要维修费如下表所示
• 如何制定设备更新计划,使得总支付费用最少?
![](https://img-blog.csdnimg.cn/img_convert/8347fd5da13f620dff8b7a9bbeacc20a.png)
❑ 题目分析
• 关键在于制定计划使“五年内总支付费用最少”
• 翻译翻译:从第1年初起,到第5年末,中间有很多选择(每一年是买新的还是用旧的)
• 第1年初=源点,第5年末=终点,每年的选择=路径,总支付费用=总路径
❑ 模型建立(重点)
• 构造有向图D,包含顶点v= {v1, v2, … ,v6,},分别代表第1年年初,第2年年初,……第5年年初,和最后v6代表第5年年末
• 顶点之间的有向边vi→vj代表“i时刻购买新设备,使用到j时刻”,该边的权重代表所两个
时刻之间购买新设备的费用与维修费用之和
• 画出该图,并写出该图的邻接矩阵𝑊:
![](https://img-blog.csdnimg.cn/img_convert/25852d2935f9fcc86f1ccc92e4787940.png)
• 整体思路就是从题目中画出图,再从图得到邻接矩阵,然后调用MATLAB函数即可求解
![](https://img-blog.csdnimg.cn/img_convert/8347fd5da13f620dff8b7a9bbeacc20a.png)
❑ 代码求解
❑ 问题求解
• 题目要求制定计划,使总支付费用最小,就是在有向图D中求从𝑣1到𝑣6的最短路径
• 有了邻接矩阵,调用matlab函数即可求解。(文末)
❑ 结果分析
• 求解得到的path=[1,3,6]
• 意味着顶点1到顶点6的最短路径为1到3再到6;
• d = 48意味着总路径长度为48;
❑ 制定计划
• 第1年年初购买新设备
• 使用到第3年年初,再购买新设备
• 使用到第5年年末
• 能使5年内总支付费用最少,最少为48万。
![](https://img-blog.csdnimg.cn/img_convert/e250a186d70ab65f5e5be5cb4c24df0d.png)
最短路径
graph:生成无向图
digraph:生成有向图
G = graph(A):使用邻接矩阵A创建无向图G,A中的元素值代表边的权重
G = graph(s,t,weights):使用顶点对组(两个矩阵)s,t和权重向量
设备更新问题
根据题目,已写出邻接矩阵:
![](https://img-blog.csdnimg.cn/img_convert/25852d2935f9fcc86f1ccc92e4787940.png)
注意:MATLAB中,不存在的边(即邻接矩阵中正无穷)的权重写作0
❑ matlab代码
% 写出邻接矩阵,先定义全是0的矩阵,再修改不是0的元素
a = zeros(6); %定义一个六行六列全是零的矩阵
a(1,[2:6])= [15 20 27 37 54]; %表示修改第一行从第二列到第六列的数值
a(2,[3:6]) = [15 20 27 37];
a(3,[4:6]) = [16 21 28];
a(4,[5:6]) = [16 21];
a(5,6) = 17;
% 给每个顶点标注名称,放在元胞s里
% int2str([1:6]')将整数1到6六个数转化为字符;[1:6]代表一个矩阵,加撇转置;int2str()转为字符;
% strcat把字符串水平串联起来,注意是水平,所以要转置变为列向量,如果用行向量,则得到的是一行"v1 2 3 4 5 6"
% strcat('v',int2str([1:6]'))把v和字符1到6拼起来,
% 得到6行的数组,分别有v1,v2等,v也可以是文字等
s = cellstr(strcat('顶点',int2str([1:6]'))); %cellstr代表字符元胞
G = digraph(a,s); % 不加s不影响求解 digraph生成图迹
% plot绘图有很多参数可以设置,使图尽量美观
P = plot(G,'layout','force','EdgeColor','k','NodeFontSize',12); %layout后面使图片美观
[path,d] = shortestpath(G,1,6); %d是最短路径的长度(主要求解代码)
% 在图片P中,设置求得的最短路径path的属性(颜色、粗细等等)
highlight(P,path,"EdgeColor","red",'LineWidth',3.5)
更改的图论的图布局,设置‘layout’。本代码中设置'layout','force',是实现在相邻节点之间使用引力,在远距离节点之间使用斥力。
先分析题目,写出矩阵,matlab设置参数,shortestpath()函数求最短路径
求解得到的path=[1,3,6]意味着顶点1到顶点6的最短路径为1到3再到6;
d = 48意味着最短路径长度为48;
![](https://img-blog.csdnimg.cn/img_convert/a1100f760a2370dbddde64171ea93e37.png)