记忆化能让这个解决方案更高效吗?
是的!
如果是这样,那么我无法将失败路径中的所有单元格列入黑名单,因为可能存在通过这些单元格的其他路径可能导致目标。
正确。
所以我很困惑我应该在这里缓存什么以及在哪里添加额外的检查以避免检查我已经通过的路径。
这就是你要做的。
创建一个可空整数的 r x c 二维数组,我们称之为a。数组的含义是“a[x][y] 给出从 (x, y) 到 (r-1, c-1) 的路径数”——假设 (r-1, c-1) 是“退出”我们试图到达的单元格。
数组将从每个元素开始为空。那太棒了。 Null 表示“我不知道”。
用零填充数组中的每个“阻塞”单元格。这意味着“没有办法从这个牢房到出口”。
如果a[r-1][c-1] 为零,则出口被阻塞,我们就完成了。每个查询的答案都是零,因为没有办法到达出口。假设出口单元没有被阻塞。
有一种方法可以从退出单元格到达自身,因此将a[r-1][ c-1] 填入 1。
现在算法是这样进行的:
- 我们被要求从单元格
(x, y) 开始提供解决方案。
- 咨询阵列。如果它为空,则在右侧和向下的邻居中递归,并在
[x][y] 处使用这些答案的sum 填充数组
- 现在数组肯定填好了,所以返回
a[x][y]。
让我们举个例子。假设我们有
n n n
n n 0
n n 1
我们被要求提供 (0, 1) 的解。我们没有解决方案。所以我们试图找到 (1, 1) 和 (0, 2) 的解。
我们没有 (1, 1) 的解决方案。所以我们必须得到 (1, 2) 和 (2, 1) 的解。
(1, 2) 我们得到了。是 0。
(2, 1) 我们没有,但 (2, 2) 我们有,这是唯一的邻居。 (2, 2) 是 1,所以我们填入 (2, 1):
n n n
n n 0
n 1 1
现在我们有足够的信息来填写 (1, 1):
n n n
n 1 0
n 1 1
我们还没有完成 (0, 2)。它有一个为零的邻居,所以是:
n n 0
n 1 0
n 1 1
现在我们可以填写 (0, 1)
n 1 0
n 1 0
n 1 1
这是我们一直在寻找的,所以我们完成了。
替代解决方案:预先计算数组。
- 我们首先像以前一样在出口处填写所有零和一个。
- 现在从下往上填写最右边的一列:全为 1,直到到达第一个零,此时它变为全零。
- 现在从右到左填写最底部的行。同样,它都是 1,直到您到达第一个零,此时它变为全零。
- 现在我们有足够的信息来填写右数第二列和倒数第二行;你明白吗?
- 这样继续,直到填满整个数组。
- 现在所有答案都在数组中。
例子:
第一步:
n n n
n n 0
n n 1
填写外行列:
n n 0
n n 0
1 1 1
填写下一行和下一列:
n 1 0
2 1 0
1 1 1
最后一个:
3 1 0
2 1 0
1 1 1
我们完成了;整个问题都解决了。
如果没有细胞被列入黑名单,那么我想知道记忆是否有任何目的。
如果没有单元格被列入黑名单,则数组如下所示:
20 10 4 1
10 6 3 1
4 3 2 1
1 1 1 1
这是您应该以前见过的形状,并且知道如何直接计算每个元素。提示:您通常将其视为三角形,而不是正方形。