Java 冗余路径的记忆
我正在解决一个问题,其中有一个包含r行和c列的网格。我们从左上角单元格开始,到右下角单元格结束。限制是我们一次只能移动一个单元格,向下或向右移动。此外,一些单元格可能被列入黑名单。问题是找到我们从源头到目标的总途径 这是我的解决方案,它简单明了,但以指数时间运行:Java 冗余路径的记忆,java,dynamic-programming,memoization,Java,Dynamic Programming,Memoization,我正在解决一个问题,其中有一个包含r行和c列的网格。我们从左上角单元格开始,到右下角单元格结束。限制是我们一次只能移动一个单元格,向下或向右移动。此外,一些单元格可能被列入黑名单。问题是找到我们从源头到目标的总途径 这是我的解决方案,它简单明了,但以指数时间运行: int count(boolean[][] array, int r, int c) { if ((r < 0 || c < 0) || !array[r][c]) return 0; if (r == 0
int count(boolean[][] array, int r, int c)
{
if ((r < 0 || c < 0) || !array[r][c]) return 0;
if (r == 0 && c == 0) return 1;
return count(array, r - 1, c) + count(array, r, c - 1);
}
int计数(布尔[][]数组,int r,int c)
{
if((r<0 | | c<0)| |!数组[r][c])返回0;
如果(r==0&&c==0)返回1;
返回计数(数组,r-1,c)+计数(数组,r,c-1);
}
我遇到的问题是在回忆这件事的时候
a
。数组的含义是“a[x][y]
给出从(x,y)到(r-1,c-1)的路径数”——这是假设(r-1,c-1)是我们试图到达的“出口”单元
数组将以每个元素为空开始。太好了。Null表示“我不知道”
在数组中的每个“阻塞”单元格中填入零。这意味着“没有办法从这个牢房到出口”
如果a[r-1][c-1]
为零,那么出口被阻塞,我们就完成了。每个查询的答案都是零,因为无法到达出口。假设退出单元没有被阻塞
有一种方法可以从出口单元格到它自己,所以用1填写a[r-1][c-1]
现在,算法是这样进行的:
20 10 4 1
10 6 3 1
4 3 2 1
1 1 1 1
- 我们需要从单元格
开始的解决方案(x,y)
- 查阅数组。如果为空,则在右下邻域递归,并用这些答案的总和填充
处的数组[x][y]
- 现在数组肯定已填充,因此返回
李>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,2)是1,所以我们填写(2,1):
现在我们有足够的信息来填写(1,1):
我们还没有完成(0,2)。它有一个邻居是零,所以:
n n 0
n 1 0
n 1 1
现在我们可以填写(0,1)
这就是我们一直在寻找的,所以我们完成了
替代解决方案:预计算阵列
- 我们开始填写所有的0和出口处的1,就像以前一样李>
- 现在从下往上填充最右边的一列:它是全1,直到你到达第一个零,在这一点上它变成全0李>
- 现在从右向左填写最下面一行。同样,它是全1,直到你到达第一个零,在这一点上它变成全0
- 现在我们有足够的信息来填写右栏的第二个和底行的第二个;你看到了吗
- 继续这样操作,直到填充完整个数组
- 现在所有答案都在数组中
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
填写下一行和下一列:
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
这是一个你以前应该见过的形状,并且知道如何直接计算每个元素。提示:您通常将其视为三角形,而不是正方形
记忆化能使这个解决方案更有效吗
对!
如果是这样的话,那么我就不能将失败路径中的所有单元都列入黑名单,因为可能有其他路径通过这些单元,从而导致目标
对
所以我很困惑,我应该在这里缓存什么,在哪里添加额外的检查以避免检查我已经通过的路径
这是你要做的
制作一个由可空整数组成的rxc2-d数组,我们称之为a
。数组的含义是“a[x][y]
给出从(x,y)到(r-1,c-1)的路径数”——这是假设(r-1,c-1)是我们试图到达的“出口”单元
数组将以每个元素为空开始。太好了。Null表示“我不知道”
在数组中的每个“阻塞”单元格中填入零。这意味着“没有办法从这个牢房到出口”
如果a[r-1][c-1]
为零,那么出口被阻塞,我们就完成了。每个查询的答案都是零,因为无法到达出口。假设退出单元没有被阻塞
有一种方法可以从出口牢房出来