我有一个N×N网格,每个框都有值。我必须从左上角移动到右下角(路径1),从右上角移动到左下角(路径2)。当我从左上角移动到右下角时,我只能向下或向右移动。同样,当我从右上角移动到左下角时,我只能左右移动。
但如果我在走路1时向下移动,路径2的相应移动应该在左边。类似地,如果我在采用路径1时向右移动,则路径2的相应移动应该是向下的。
当我们采用两条路径时,我们总结了每个框中遇到的值。我们可以获得的最大值是多少?
以下面的网格为例:
6 0 3 -1
7 4 2 4
-3 3 -2 8
13 10 -1 -4
我们可以采用的最佳路径表示如下:路径1由*表示,而路径2由〜表示。
(6*) (0) (3~) (-1~)
(7*) (4*~) (2~) (4)
(-3) (3*~) (-2*) (8*)
(13~) (10~) (-1) (-4*)
这两条路径的总和是56.
我们必须设计一种算法来计算给定任意N×N网格的最大可能得分。
很明显这是一个DP问题。所以,我试图确定一个递归关系,可以这么说。我尝试使用从N乘M网格中找到所有路径的最大总和的经典问题的递归关系,但这不起作用,因为它太复杂了。
我试图将N乘N网格划分为四个(N-1)个重叠的网格(N-1),因此在3乘3网格中进行演示:
a1 a2 a3
a4 a5 a6
a7 a8 a9
我把它分为四个2 x 2网格:
a1 a2 , a2 a3 , a4 a5 , a5 a6
a4 a5 , a5 a6 , a7 a8 , a8 a9
假设我们知道所有这些网格的最佳路径,那么我们可以为更大的网格计算最佳路径吗?
嗯,这似乎很有希望,但我很快发现这些复发关系,取决于更大的案例。例如,
如果我们考虑第二个2 x 2网格,假设我们知道最佳路径1和路径2 = S.现在,显然,对于我们从a1到a2,我们需要向右移动,但这意味着在子案例中的第一次移动(路径2中的第一次移动)应该是向下移动,这是不能保证的。
我们如何解决这个问题?
答案 0 :(得分:4)
移动这两个点的规则相当于通过网格找到单个路径,该网格是网格和自身旋转-90度(向左90度/逆时针/逆时针90度)的总和,具体取决于您的区域设置)。
左上角的“向下”对应于右上角的“左”,当旋转-90度时,它向下。左上角的“右”对应于右上角的“向下”,当旋转-90度为右时。 (知道吗?)
所以你的示例网格是
6-1 0+4 3+8 -1-4 5 4 11 -5
7+3 4+2 2-2 4-1 10 6 0 3
=
-3+0 3+4 -2+3 8+10 -3 7 1 18
13+6 10+7 -1-3 -4+13 19 17 -4 9
现在,您可以通过任何常用方法找到从左上角到右下角的路径。实际上,您不需要路径,只需要最大总和,这更容易:通过添加从左上角向下折叠矩阵。初始条件是上面的网格。下一步是将左上角的值添加到其有效的邻居:
9 11 -5
15 6 0 3
-3 7 1 18
19 17 -4 9
然后选择具有两个有效邻居的任何网格点的两个邻居中较大的一个(这里21大于20和12):
20 -5
21 0 3
12 7 1 18
19 17 -4 9
等等......
15
21 3 24
->
28 1 18 29 18 -> 47
->
31 17 -4 9 48 -4 9 44 9 56
我刚刚手动解决了你的4x4案例,答案是56.
答案 1 :(得分:1)
您可以将此减少到一个网格上只有一个路径的情况。制作网格的第二个副本,旋转第二个副本,然后将它们矩阵添加在一起,并使用一个路径在新网格上求解。动态编程问题很容易(即为每个节点计算部分最大值)。