我有一个矩阵(地图)的问题,从左上角开始,我想找到右下角较重的路径。它的条件是它只能向右,向下或向右下移。
这是一个例子: matrix example
我需要用回溯来解决问题,但我不知道我是否做得很好。
此代码能够解决高达10x10的矩阵大小,但是当我尝试使用20x20矩阵时,它会被卡住(或者至少是我在下班后的想法)。
/*
* i, j -> matrix iterators.
* n, m -> matrix height and width
* map -> matrix
* actualPath, bestPath -> vectors for representing the path later
* actual -> actual path weight
* best -> best path weight
*/
int backtracking(int i, int j, const int &n, const int &m,
const vector<vector<int>> &map,
vector<vector<int>> &actualPath,
vector<vector<int>> &bestPath,
int best) {
recursiveCalls++;
int actual = 0;
//Bottom-right corner
if(i == (n-1) && j == (m-1)) {
return map[i][j];
}
//Last row, only right
else if(i == (n-1)) {
actual = map[i][j] +
backtracking(i, (j+1), n, m, map, actualPath, bestPath, best, profundidad);
}
//Last column, only down
else if(j == (m-1)) {
actual = map[i][j] +
backtracking((i+1), j, n, m, map, actualPath, bestPath, best, profundidad);
}
else {
int downRight = backtracking((i+1), (j+1), n, m, map, actualPath, bestPath, best, profundidad);
int right = backtracking(i, (j+1), n, m, map, actualPath, bestPath, best, profundidad);
int down = backtracking((i+1), j, n, m, map, actualPath, bestPath, best, profundidad);
actual = map[i][j] + minimo(downRight, right, down);
}
if(actual < best) {
best = actual;
bestPath = actualPath;
}
return best;
}
它是否可能因为我不使用边界而卡住了?或者实施不好? 我不知道我做错了什么。我想我理解这个算法,但我想我不知道如何为这个问题实现它...
答案 0 :(得分:1)
虽然回溯会给你正确答案。在这种情况下,它不是最快的解决方案。
你在这里做了很多重复的工作,这是没有必要的。在这种情况下,简单的回溯功能无用。让我们来看看这个例子,
假设网格大小为10X10
。
one of the trees of the backtrackting stared from (0,0) -> (0,1)
another started from (0,0) -> (1,0)
and another started from (0,0) -> (1,1)
当第一次遍历到达点(5,5)时,它将继续寻找所有可能的方法(9,9)。现在第二次遍历达到(5,5)时,它将完成第一次遍历从此阶段完成的相同工作,第三次遍历也是如此。因此,这些重复的步骤是您耗尽程序的地方,并且您的代码执行时间太长。你的代码并没有停留很长一段时间。您可以轻松地记住结果以优化时间。
因此,如果您可以将第一次到达某一点(i,j)时找到的值保存为save[i][j]
,那么当其他一些遍历到达同一点(i,j)时,它可以决定不进一步遍历并使用此save[i][j]
作为自己的。这样,您可以更快地使代码更快。
通过这种方式,它将变得比回溯更具动态编程,即使是大小为10000X10000的网格也需要几秒钟才能得到结果。
在这个答案中,我只描述了如何找到路径值到最小值,如果你想找到也可以使用同一个DP解决方案的路径。