matlab二维路径,寻找二维数组中最短路径的matlab实现

这是一道比较有意思的题目,给定一个数字方阵,你只能向右或者向下走,让你寻找从左上角到右下角的一条路径,且让这条路径所经过的数字之和最小。

我将以下面这个方阵为例讲解一些较为关键的算法思路。现在给你如下方阵,如何找出一条数字和最小的路径呢?

048a84b401fd0cda6f1a0f1b1827e45b.png

最简单粗暴的方法就是把所有的路径找出来,计算每一条路径的值,然后进行比较,找出那条最短路径。但我们不需要这么做,毕竟设计一个遍历所有路径的算法还是挺复杂的。我们知道,最短路径的子路径也一定最短,从这一点出发便可以大大简化我们算法的设计-------我们只需要找出最短的一条子路径,然后沿着最短子路径再寻找其他最短子路径就可以了。

我们可以从第一行开始,很显然,第一行每一条子路径都是最短的,因为只有一条路径,因此我们可以对每条路径进行求和(这里得提醒一下每条路径的起点都是数组的左上角)。同理,第一列也是如此。我们可以将每条路径的值存入一个新的数组中,终点对应的位置存放这条路径的值,如下图所示:

df46cc0ec85c6f650098b08ea858f39a.png

接下来我们从第二行第二列的元素开始,为表示方便我们记为(2,2),(i,j)表示第i行第j列。由于起点是(1,1),我们只能向右或向下,因此能到达(2,2)的上一个结点的位置只有(1,2)和(2,1),我们很容易就能发现,在路径值数组中(1,2)是最小的,也就是说(1,1)->(1,2)->(2,2)和(1,1)->(2,1)->(2,2)这两条子路径中,前者数值之和更小,因此前者为最短路径。因此,路径值数组中(2,2)的值应为(1,1)->(1,2)->(2,2)这条路线上的数字之和,即14+11=25,如图:

c8d2901cf2521155292b0bb2f68f43b7.png

把这一步弄明白以后,路径值数组里其他元素的值也都出来了。

4fbbb3522c527048feb54efeeef12d6a.png

这里还需要再提一下,路径值数组里每个元素的意义,它里面每一个元素表示的意义是从起点到这个元素所在的位置的最短路径的值,比如路径值数组(右图)第五行第五列是66,表示从原数组从(1,1)到(5,5)的最短路径值是66。如果只是想得到最短路径的结果,做到这一步就可以了,但我还想知道这条路线具体经过了哪里,该怎么做呢?

方法其实很简单,我们从终点(5,5)开始,现在看向右图路径值矩阵,你现在站在(5,5)这个位置,你看向你的上方(4,5)(upon)和左方(5,4)(left),你发现左边的值更小(left < upon),于是你向左边走了一步,这时候你在(5,4),同时记录下了你所在的位置......依此类推,最终你会回到起点(1,1),同时也得到了这条最短路线(下面左图中红色标记的部分):

0e792ffb121ad801ae1bd0cdd7137df7.png

233fded2c14caa42baa28410480486ec.png

58a460dc0e924fc5e99d7e325cd0edf7.png

这就是我们的最短路径了。

有一个小细节可以注意一下,注意到右图的(4,3),你会发现左方和上方的值是一样的,也就是说这个数组其实有多条不同的最短路径。我的程序中默认当遇到值相等的时候就向左走(上面的例子是向上走),因此最终只会有一条路径。

还有一个小问题可以小小思考一下,这是一个在调试程序的时候出现的小问题:如果我走到了边界(未到终点),这时候看不到左方或者上方了,该怎么把这条路线全都标记出来呢?

以下附上程序源码:

主程序运行函数Main.m

clear;close all;clc;

%给定n*n的随机路径,也可以自己设置

maze = floor(rand(5) * 15);

[ShortestPathValue,index] = FindPath2D(maze); % ShortestPathValue : 最短路径的数值矩阵

% index : 显示找到的最短路径

调用的FindPath2D.m函数:

function [ShortestPathValue,index] = FindPath2D(maze)

% 函数功能:输入矩阵,输出最短路径值以及路线(方向从左上到右下)

if isempty(maze)

disp('path is empty');

return;

end

[m,n] = size(maze);

data = zeros(m,n);

index = zeros(m,n);%用来标记最短路径的路线

% 计算第一行和第一列的最短路径值

for p = 2:n

data(1,p) = sum(maze(1,1:p));

end

for p = 2:m

data(p,1) = sum(maze(1:p,1));

end

% 计算各个子路径终点的最短路径值

for p = 2:m

for q = 2:n

data(p,q) = maze(p,q) + min(data(p-1,q),data(p,q-1));

end

end

ShortestPathValue = data;

% 将起点和终点标记为1

index(1,1) = 1;

index(m,n) = 1;

p = m;q = n; %注意是从终点向起点方向标记最短路径

%data(p,q)是你所在的位置

while 1

if p == 1 & q == 1 %判定是否到达终点

break;

elseif p == 1 %判定是否到达边界

index(1,1:q) = 1;

break;

elseif q == 1 %判定是否到达边界

index(1:p,q) = 1;

break;

end

left = data(p-1,q);%向左

upon = data(p,q-1);%向上

%根据左边和上边的值来判定行进方向,相等则默认向左

if left <= upon

index(p-1,q) = 1;

p = p - 1;

elseif upon <= left

index(p,q-1) = 1;

q = q - 1;

end

end

其中一组运行结果:

6891c57144cc1a311d87891cf0f72ae6.png

2f225fcb89953a17f86997487199b8e4.png

e36503e963d15918c69f6c41d9b6a0a9.png

二维数组的最短路径其实很简单,目前正在做三维数组最短路径的代码编写。这远远没有我当时想像的那么简单,要考虑的东西很多,等做出来了再另写一篇吧。

对这程序有什么疑问或者对matlab语言还不太熟悉的,可以在下方留言,我看到后会尽快答复,或者联系

qq:1765928683

邮箱:kelrays@qq.com

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值