动态规划求最短路径(matlab代码)

此题目来源于算法分析与设计课程中,老师给的一个练习题。

设计一个动态规划算法求解下述多段图问题,计算从第一段源点(示例图中节点0)到最后一段目标节点(示例图中节点15)的最短路径:
动态规划求最短路径(matlab代码)_第1张图片
关于动态规划的思想,b站上有位老师讲得比较清晰易懂(链接视频)。本解题思路也来源于此。

简单说一下解题思路。从目的端(15节点)开始,往上走,到13、14节点那一层,记录下该层节点(即13、14)到下一层节点(即15)的最短路径值。以此类推,再往上走,同样记录下该层节点到下一层的最段路径,直到走到源端(即上图中的0)。如下图所示,记录下的最短路径值:
动态规划求最短路径(matlab代码)_第2张图片
由上图可知,通过手算,得到该图的最短路径值为18。当然此处数据量不算太大,手算当然可以,但是当数据量更大时就很费劲了。

这里给出该图的matlab求解程序。

此处对于原问题中,各个路径的值用cell数据结构来存储。cell数据结构还真挺好用的,我也是前段时间频繁接触它。本程序对cell的使用还比较浅。cell相当于一个容器,按本程序来理解,容器里装了一些对象,这里设置了6个对象,对应图的6层(不包含最后一层),这里将倒数第二层作为第1个对象。

为什么说cell好用,就是因为cell对于每个对象的大小没有统一的限制。这里每个对象就是一个矩阵,矩阵的大小根据本层节点数(作为行数)和下层节点数+1(作为列数)来决定,这里列数加1,是为了存最短路径。当某节点到下一层节点没有路径时,将其初始化为999(一个比较大的值)。

这里要注意cell结构中对象赋值、元素存取等,看得多了就理解了。

Path_w=cell(6);
Path_w{6}=[5,3,0];%第一层1个节点,所以1行,下一层2个节点,所以列数是2+1,最后一个用来存最短路径
Path_w{5}=[1,3,6,999,0;999,8,7,6,0];
Path_w{4}=[6,8,999,0;3,5,999,0;999,3,3,0;999,8,4,0];
Path_w{3}=[2,2,999,0;999,1,2,0;999,3,3,0];
Path_w{2}=[3,5,0;5,2,0;6,6,0];
Path_w{1}=[4,4;3,3];
%Not include last layer

flag=cell(6);%这是为了存储最终的最短路径都经过了哪些节点
flag{1}=[1,1];

for i=2:length(Path_w)
    if size(Path_w{i-1},1)==1%前一层的节点只有1个时。本题中未将最后一层节点放进来,所以按逻辑,此if应该不会进来。
        for m=1:size(Path_w{i},1)
            Path_w{i}(m,end)=Path_w{i}(m,1)+Path_w{i-1}(1,end);
        end          
    else
        for m=1:size(Path_w{i},1)%size(Path_w{i},1)表示第i个对象矩阵的行数 即第i层节点数
            current_min=99999;
            for n=1:size(Path_w{i},2)-1
                if Path_w{i}(m,n)+Path_w{i-1}(n,end)<current_min
                    current_min=Path_w{i}(m,n)+Path_w{i-1}(n,end);
                    flag{i}(m,1)=n;
                end
            end
            Path_w{i}(m,end)=current_min;
        end
    end
end
disp("shortest path cost:");disp(Path_w{6}(1,end));
disp("从左到右每层选择的节点是:")
result=flag{length(flag)};
disp(result);
for i=length(flag)-1:-1:1
    result=flag{i}(result);
    disp(result);
end

得到结果如下:
动态规划求最短路径(matlab代码)_第3张图片
每层选择的节点如下:
动态规划求最短路径(matlab代码)_第4张图片
即选择节点为:0,1,4,7,11,14,15。

你可能感兴趣的:(笔记,matlab,动态规划,算法)