回溯法(Backtracking)是一种递归形式的算法。
该基于布尔值的算法面临选择,然后进行选择,并在初始选择后呈现一组新的选择。
从概念上讲,您从树的根部开始;树可能有一些好的叶子和一些坏的叶子,尽管叶子可能全部是好的或全部是坏的。您想到达一个好的叶子。从根节点开始,每个节点选择其要移动到的一个子节点,一直保持下去,直到到达叶子节点。(见下图)
示例说明:
来源:upenn.edu
“回溯”是在枚举算法中出现的术语。
您构建了一个“解决方案”(即,每个变量都被分配了一个值的结构)。
然而,在构建过程中,可能会意识到该解决方案不成功(不满足某些约束条件),然后您需要回溯:撤消对变量赋值的某些操作以重新分配它们的值。
例子:
根据您的示例,您希望在2D网格中构造路径。因此,您从(0,0)开始生成路径。例如:
(0,0)
(0,0) (1,0) go right
(0,0) (1,0) (1,1) go up
(0,0) (1,0) (1,1) (0,1) go left
(0,0) (1,0) (1,1) (0,1) (0,0) go down
Oops, visiting a cell a second time, this is not a path anymore
Backtrack: remove the last cell from the path
(0,0) (1,0) (1,1) (0,1)
(0,0) (1,0) (1,1) (0,1) (1,1) go right
Oops, visiting a cell a second time, this is not a path anymore
Backtrack: remove the last cell from the path
....
事实上,“回溯”一词在“回溯法”中有时会让人感到困惑,因为在解决经典的N皇后问题时,回溯解决方案“继续向前走”:
/**
* Given *starting* row, try all columns.
* Recurse into subsequent rows if can put.
* When reached last row (stopper), increment count if put successfully.
*
* By recursing into all rows (of a given single column), an entire placement is tried.
* Backtracking is the avoidance of recursion as soon as "cannot put"...
* (eliminating current col's placement and proceeding to the next col).
*/
int countQueenPlacements(int row) { // queen# is also queen's row (y axis)
int count = 0;
for (int col=1; col<=N; col++) { // try all columns for each row
if (canPutQueen(col, row)) {
putQueen(col, row);
count += (row == N) ? print(board, ++solutionNum) : countQueenPlacements(row+1);
}
}
return count;
}
来自维基百科:
回溯法是一种用于找到某些计算问题的所有(或某些)解的通用算法,它逐步构建解的候选并放弃每个部分候选c(“回溯”),只要它确定c不可能完成为有效的解。
回溯法很容易作为递归算法实现。您通过寻找大小为n-1的解决方案来寻找大小n问题的解决方案等等。如果小尺寸的解决方案不起作用,则将其丢弃。
基本上,上面的代码是在做什么:在基本情况下返回true,否则它会'尝试'右路径或左路径,丢弃不起作用的解决方案。
由于上面的代码是递归的,可能不清楚“回溯”何时发挥作用,但算法实际上是从部分解构建解决方案,其中最小可能的解决方案在您的示例中在第5行处理。非递归版本的算法必须从最小解开始构建。
我不明白"回溯算法"是什么意思。
当一个算法尝试一种解决方案,失败后返回到更简单的解决方案作为新尝试的基础时,它被称为"回溯"算法。
在这个实现中,
current_path.remove(p)
current_path
的路径的不同变体。