回溯算法卡住了
Backtracking algorithm gets stuck
我有一个从左上角开始的矩阵(地图)的问题,我想找到到右下角的较轻的路径。它有条件只能向右、向下或右下移动。
这是一个例子:
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;
}
会不会因为我没有使用bounds而卡住?还是实施不好?
我不知道我做错了什么。我想我理解这个算法,但我想我不知道如何针对这个问题实现它...
虽然回溯会在这里给你正确的答案。在这种情况下,它不是最快的解决方案。
你在这里做了很多重复的工作,这是没有必要的。直接回溯在这种情况下没有用。让我们看看这个例子,
假设网格大小为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 解决方案的路径。
我有一个从左上角开始的矩阵(地图)的问题,我想找到到右下角的较轻的路径。它有条件只能向右、向下或右下移动。
这是一个例子: 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;
}
会不会因为我没有使用bounds而卡住?还是实施不好? 我不知道我做错了什么。我想我理解这个算法,但我想我不知道如何针对这个问题实现它...
虽然回溯会在这里给你正确的答案。在这种情况下,它不是最快的解决方案。
你在这里做了很多重复的工作,这是没有必要的。直接回溯在这种情况下没有用。让我们看看这个例子,
假设网格大小为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 解决方案的路径。