问题是我想从右上角到左下方有一个最大的数字总和,我只需要12次移动,实际上这是化学。工程。问题,但解决的简单方法是我提到的要点,我知道这些类型的问题在图形和一些算法中有一些理论,但由于我是一名化学工程专业的学生,我不太熟悉图形和相关的算法。 我努力想出一个想法,但实际上我找不到,我很感激你的想法。
我使用了答案,我得到了这个:(从左下到右上,所以移动是从下到上,从左到右,从节点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
答案 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
个节点,邻接矩阵A
为n 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.04
,14
到13
等等。
创建有向图
要将此信息提供给MATLAB的图形算法,您需要使用函数digraph
创建正确的结构,
G = digraph(A);
或
G = digraph(s, t, w);
取决于您选择的代表。
使用最短路径算法
获得G
后,只需拨打shortestpath即可。由于我们使用原始权重的负数,这实际上是最长的路径。您还需要为路径指定开始和结束节点。使用我的编号,这将是start_node = 7
和end_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
,那么它可能没那么重要,您可以采用默认值。