What is the standard backtracking template, and what are its parts?
Backtracking is recursion with the ability to undo a choice. The template has four parts that appear in every backtracking function.
First, the state. This is the data the search carries with it, such as the current combination, the remaining target, or a set of used positions. Second, the choice loop, which iterates over the options available at this level. Third, the explore step, which makes the choice, updates the state and recurses. Fourth, the undo step, which restores the state to what it was before the choice, so the next iteration starts from a clean slate.
def search(state, remaining):
if remaining == 0:
record(state)
return
for option in options(state):
apply(option)
search(new_state, new_remaining)
undo(option)The undo step is the one that gets forgotten, and it is the one that decides whether the algorithm is correct. If you forget to undo, the state leaks between branches and you will produce wrong answers or miss valid ones.
The mechanism is that the recursion explores a tree of choices. The number of nodes in that tree is what determines the running time, and pruning is the art of not visiting the nodes that cannot lead to a valid answer. A branch is pruned when the remaining target is already zero, when an option exceeds what is left, or when the remaining options cannot possibly fill the gap.
The trade-off to name is that the output size is often the bound. For problems like subsets, permutations and combination sum, the number of valid answers is enormous, so the search cost is at least the cost of producing them. Pruning does not change that lower bound, it only removes the wasted branches. And the state has to be copied when you record an answer, because the list you are carrying keeps changing as the search continues.