【问题标题】:Optimal path through a matrix with multiple costs to consider需要考虑多个成本的矩阵中的最优路径
【发布时间】:2020-05-28 10:35:19
【问题描述】:

例如给定以下矩阵:

[[[0, 8], [0, 3], [0, 8]],
 [[8, 0], [3, 0], [0, 5]],
 [[0, 1], [0, 6], [0, 0]]]

每个元组的第一个数字是食物,第二个数字是水。我需要从右下角到左上角,我只能向上或向左移动。

我需要收集尽可能多的食物和水,这样我才能尽可能地活下去。对于我想要生存的每一天,我需要 1 份食物和 1 份水,所以如果我可以在导致 (7,4) 的路径和会导致 (6,6) 的路径之间进行选择,正确的选择是 (6,6 ) 因为这样我可以活 6 天。

如何通过所述矩阵找到最佳路径?

我当前的代码在下面,但是它不起作用(它找到了一个非常高成本的路径,但不是最高的),我不知道如何去做。尽管有人告诉我要避免递归,但我不知道如何开始实现它。

def maxSuppliesPath(matrix):
n = len(matrix) - 1
bestPath = matrix

# Initialize first column of bestPath array
for i in range(1, n + 1):
    if bestPath[i][0] == 0:
        bestPath[i][0] = bestPath[i - 1][0]
    else:
        bestPath[i][0] = (bestPath[i][0][0] + bestPath[i - 1][0][0], bestPath[i][0][1] + bestPath[i - 1][0][1])

# Initialize first row of bestPath array
for j in range(1, n + 1):
    if bestPath[0][j] == 0:
        bestPath[0][j] = bestPath[0][j - 1]
    else:
        bestPath[0][j] = (bestPath[0][j - 1][0] + bestPath[0][j][0], bestPath[0][j - 1][1] + bestPath[0][j][1])



# Construct rest of the bestPath array
for i in range(1, n + 1):
    for j in range(1, n + 1):
        if min(bestPath[i][j - 1][0] + bestPath[i][j][0], bestPath[i][j - 1][1] + bestPath[i][j][1]) > min(
                bestPath[i - 1][j][0] + bestPath[i][j][0], bestPath[i - 1][j][1] + bestPath[i][j][1]):
            bestPath[i][j] = (bestPath[i][j - 1][0] + bestPath[i][j][0], bestPath[i][j - 1][1] + bestPath[i][j][1])
        else:
            bestPath[i][j] = (bestPath[i - 1][j][0] + bestPath[i][j][0], bestPath[i - 1][j][1] + bestPath[i][j][1])

return min(bestPath[n][n][0], bestPath[n][n][1])

【问题讨论】:

  • 我已经为你改了,虽然我不明白为什么方向会改变答案?
  • 好的,谢谢,我一直在互联网上搜索任何讨论像我这样的问题的东西,但到目前为止我没有运气,尽管有大量关于路径查找的帖子只涉及一个值。
  • 我添加了一些解释性文字。如果您有任何问题,请告诉我。

标签: python matrix optimization path-finding


【解决方案1】:

解决问题的第一步是了解如何遍历矩阵。下图显示了从起点到其他点的距离。

请注意,等距点排列在对角线上。给定一个代表一条对角线的set(称为A),可以找到下一条对角线(称为B)上的点,如下所示:

for each point in set A
    if the x coordinate is greater than zero
        add (x-1, y) to set B
    if the y coordinate is greater than zero
        add (x, y-1) to set B

在示例中,表示对角线的集合应如下所示:

[(2, 2)]                  // starting position
[(1, 2), (2, 1)]          // after 1 move
[(2, 0), (1, 1), (0, 2)]  // after 2 moves
[(0, 1), (1, 0)]          // after 3 moves
[(0, 0)]                  // after 4 moves

下图显示了可以使用多少条不同的路径到达矩阵中的每个点。路径数与Pascal's triangle 中的数字相同。就这个问题而言,唯一重要的是数字增长很快,因此我们需要减少计数。

为了减少路径计数,我们需要在遍历矩阵时剔除非生产路径。这是通过比较元组来完成的,其中每个元组由食物和水组成。一个元组 (F,W) 支配一个元组 (f,w) iff F >= f AND W >= w

例如,考虑矩阵中的中心位置。我们可以通过先上后左移动或先左后上移动来达到该点。 (3,5) 的产量(食物、水)先上后移,而左后上移产量(3,6)。 (3,6) 支配 (3,5),所以我们只需要考虑 (3,6)。所以经过两次移动,我们就有了下图所示的情况。请注意,我们在中心位置只有 1 个元组,而不是帕斯卡三角形预测的两个。

经过三步后,我们有如下所示的情况。第三条对角线上的每个点都有两个元组。这是必要的,因为其中一个元组有更多的食物,而另一个有更多的水,所以两者都不占主导地位。

四步之后,我们有四个可能的答案,选择最佳答案很简单,只需比较每个元组的min(food, water)

【讨论】:

  • 谢谢这是一个很好的解释。我的一个问题是存储每个位置的可能值的最佳方法是什么?使用列表或字典?
  • @JulienPowell 好问题。我采取了简单的方法,并列出了列表列表。列表列表代表矩阵的行和列,每个位置都有一个可能值的列表。为了能够打印最佳路径,每个可能的值还需要有一个from 字段。在示例中,矩阵的顶部中心条目 (matrix[0][1]) 将包含具有两个条目的元组列表:[(0,16,'R'), (3,9,'D')],这意味着 0,16 来自右侧,3,9 来自下方。
猜你喜欢
  • 2018-04-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多