两点之间的最长路径

时间:2016-07-15 14:41:49

标签: matlab

问题是我想从右上角到左下方有一个最大的数字总和,我只需要12次移动,实际上这是化学。工程。问题,但解决的简单方法是我提到的要点,我知道这些类型的问题在图形和一些算法中有一些理论,但由于我是一名化学工程专业的学生,​​我不太熟悉图形和相关的算法。 我努力想出一个想法,但实际上我找不到,我很感激你的想法。

  • 注意:我们只允许进行水平和垂直移动

enter image description here

我使用了答案,我得到了这个:(从左下到右上,所以移动是从下到上,从左到右,从节点43到节点7):

clc
clear

A = zeros(49) ;

A(8,1) = -3.02 ;

A(1,2) = -3.1 ;
A(9,2) = -2.04 ;

A(2,3) = -2.07 ;
A(10,3) = -2.09 ;

A(3,4) = -2.01 ;
A(11,4) = -2.04 ;

A(4,5) = -3.1 ;
A(12,5) = -3.03 ;

A(5,6) = -2.06 ;
A(13,6) = -2.05 ;

A(6,7) = -3.04 ;
A(14,7) = -2.05 ;

A(15,8) = -2.04 ;

A(8,9) = -3.04 ;
A(16,9) = -2.05 ;

A(9,10) = -2.02 ;
A(17,10) = -2.01 ;

A(10,11) = -3.1 ;
A(18,11) = -2.1 ;

A(11,12) = -2.09 ;
A(19,12) = -3.1 ;

A(12,13) = -2.08 ;
A(20,13) = -2.04 ;

A(13,14) = -2.03 ;
A(21,14) = -2.06 ;

A(22,15) = -3.05 ;

A(15,16) = -2.02 ;
A(23,16) = -2.09 ;

A(16,17) = -3.05 ;
A(24,17) = -2.07 ;

A(17,18) = -3.01 ;
A(25,18) = -2.08 ;

A(18,19) = -2.09 ;
A(26,19) = -3.03 ;

A(19,20) = -2.09 ;
A(27,20) = -2.02 ;

A(20,21) = -2.04 ;
A(28,21) = -3.05 ;

A(29,22) = -3.05 ;

A(22,23) = -2.07 ;
A(30,23) = -3.09 ;

A(23,24) = -3.05 ;
A(31,24) = -3.08 ;

A(24,25) = -2.01 ;
A(32,25) = -3.05 ;

A(25,26) = -2.01 ;
A(33,26) = -3.03 ;

A(26,27) = -3.04 ;
A(34,27) = -3.1 ;

A(27,28) = -3.05 ;
A(35,28) = -2.06 ;

A(36,29) = -2.03 ;

A(29,30) = -2.05 ;
A(37,30) = -3.05 ;

A(30,31) = -2.1 ;
A(38,31) = -3.06 ;

A(31,32) = -2.09 ;
A(39,32) = -2.09 ;

A(32,33) = -2.05 ;
A(40,33) = -2.07 ;

A(33,34) = -3.08 ;
A(41,34) = -3.02 ;

A(34,35) = -3.07 ;
A(42,35) = -3.04 ;

A(43,36) = -2.08 ;

A(36,37) = -2.05 ;
A(44,37) = -2.07 ;

A(37,38) = -2.08 ;
A(45,38) = -3.1 ;

A(38,39) = -3.03 ;
A(46,39) = -2.02 ;

A(39,40) = -2.09 ;
A(47,40) = -3.05 ;

A(40,41) = -3.09 ;
A(48,41) = -2.1 ;

A(41,42) = -3.1 ;
A(49,42) = -2.07 ;

A(43,44) = -2.08 ;

A(44,45) = -3.06 ;

A(45,46) = -2.01 ;

A(46,47) = -2.1 ;

A(47,48) = -2.02 ;

A(48,49) = -2.06 ;

G = digraph(A) ;

[path,d] = shortestpath(G,43,7) ;

但是我的路径长度错误,matlab的答案是32.78,正确的答案必须是25.73。 我找到的路径是:

43 44 45 38 39 40 41 34 27 28 21 14 7

答案路径是:

43 36 29 30 31 24 25 18 19 20 13 14 7

1 个答案:

答案 0 :(得分:3)

由于可用移动的限制,您可以将问题建模为有向非循环图。正如Longest path problem上的维基百科文章中所述,您可以通过将所有边权重w转换为-w并在结果图上应用Dijkstra's shortest path algorithm来解决此问题。

你的图表是非循环的这一事实在这里至关重要,因为这意味着不存在会导致Dijkstra失败的负权重循环。

在2015b中,MATLAB引入了新的图形函数,包括一个名为shortestpath的函数。这就是我们将要使用的内容。

图表表示

首先,您需要构建图表。有几种方法可以表示图形,在这种情况下使用哪种方法只是一个对您更有意义的问题。我们无论如何都要将这些信息传递给MATLAB的digraph,所以只要我们给它可接受的输入就可以了。

无论哪种方式,您首先需要为节点编号(图片中的网格交叉点)。只要你保持一致,你如何给它们编号并不重要。我会在第一行编号1-49:1-7,在第二行编号为8-14,依此类推,直到底行为43-49。这是一个网格右上角的几个节点的图表,我将用于演示目的。 (请记住,我们将所有边缘权重更改为负数,以便找到最长的路径。)

              (-2.06)      (-3.04)
<--------  5 <--------  6 <--------  7
           |            |            |
           |(-3.03)     |(-2.05)     |(-2.05)
           |            |            | 
           v  (-2.08)   v  (-2.03)   v
<-------- 12 <-------- 13 <-------- 14
           |            |            |
           |(-3.10)     |(-2.04)     |(-2.06)
           |            |            | 
           v  (-2.09)   v  (-2.04)   v
<-------- 19 <-------- 20 <-------- 21
           |            |            |
           |            |            |
           |            |            |
           v            v            v

邻接矩阵

表示这种情况的一种方法是使用邻接矩阵。对于n个节点,邻接矩阵An x n。在我们的例子中,我们将有一个49 x 49矩阵。如果从节点A(i, j)到节点0没有边缘,则矩阵i中的每个元素都是j,或者它是边的权重。因此,元素A(7, 6)将包含-3.04,因为这是从节点7到节点6的边的权重。所以,你只需要创建邻接矩阵

A = zeros(49, 49);

并开始在正确的位置填充边缘重量。

A(7, 6) = -3.04;
A(14, 13) = -2.03;
A(13, 12) = -2.08;
and so on...

边缘列表

表示图表的另一种方法是使用边缘列表。使用此方法,您将使用三个长度为n x n的向量,而不是单个m矩阵,其中m是图表中的边数。第一个向量s是每个边的起点(源)。第二个向量t是每个边的结束(接收器)。最后一个向量包含相应边的权重。因此,使用邻接矩阵示例中的三条边,这些矩阵看起来就像这样。

s = [ 7,    14,    13,    ...]
t = [ 6,    13,    12,    ...]
w = [-3.04, -2.03, -2.08, ...]

此处,我们从节点7到节点6的重要-3.041413等等。

创建有向图

要将此信息提供给MATLAB的图形算法,您需要使用函数digraph创建正确的结构,

G = digraph(A);

G = digraph(s, t, w);

取决于您选择的代表。

使用最短路径算法

获得G后,只需拨打shortestpath即可。由于我们使用原始权重的负数,这实际上是最长的路径。您还需要为路径指定开始和结束节点。使用我的编号,这将是start_node = 7end_node = 43

path = shortestpath(G, start_node, end_node);

这是您可能需要进行一些实验的部分。 shortestpath函数实际上有另一个参数可以传递:

path = shortestpath(G, start_node, end_node, 'Method', <algorithm>);

将使用<algorithm>参数允许您选择最短路径算法。如果您未指定'Method',我可以在documentation中看到,由于负边缘权重,它将默认为'Method', 'mixed'。这应该工作得很好,并给你最长的路径。另一个看起来很有趣的选项是'Method', 'acyclic',这可能会提高较大图形的性能。如果您的网格总是7 x 7,那么它可能没那么重要,您可以采用默认值。