Revisit the English version (#1835)

* Review the English version using Claude-4.5.

* Update mkdocs.yml

* Align the section titles.

* Bug fixes
This commit is contained in:
Yudong Jin
2025-12-30 17:54:01 +08:00
committed by GitHub
parent 091afd38b4
commit 45e1295241
106 changed files with 4195 additions and 3398 deletions

View File

@@ -1,45 +1,45 @@
# Backtracking algorithms
# Backtracking Algorithm
<u>Backtracking algorithm</u> is a method to solve problems by exhaustive search. Its core concept is to start from an initial state and brutally search for all possible solutions. The algorithm records the correct ones until a solution is found or all possible solutions have been tried but no solution can be found.
<u>The backtracking algorithm</u> is a method for solving problems through exhaustive search. Its core idea is to start from an initial state and exhaustively search all possible solutions. When a correct solution is found, it is recorded. This process continues until a solution is found or all possible choices have been tried without finding a solution.
Backtracking typically employs "depth-first search" to traverse the solution space. In the "Binary tree" chapter, we mentioned that pre-order, in-order, and post-order traversals are all depth-first searches. Next, we are going to use pre-order traversal to solve a backtracking problem. This helps us to understand how the algorithm works gradually.
The backtracking algorithm typically employs "depth-first search" to traverse the solution space. In the "Binary Tree" chapter, we mentioned that preorder, inorder, and postorder traversals all belong to depth-first search. Next, we will construct a backtracking problem using preorder traversal to progressively understand how the backtracking algorithm works.
!!! question "Example One"
!!! question "Example 1"
Given a binary tree, search and record all nodes with a value of $7$ and return them in a list.
Given a binary tree, search and record all nodes with value $7$, and return a list of these nodes.
To solve this problem, we traverse this tree in pre-order and check if the current node's value is $7$. If it is, we add the node's value to the result list `res`. The process is shown in the figure below:
For this problem, we perform a preorder traversal of the tree and check whether the current node's value is $7$. If it is, we add the node to the result list `res`. The relevant implementation is shown in the following figure and code:
```src
[file]{preorder_traversal_i_compact}-[class]{}-[func]{pre_order}
```
![Searching nodes in pre-order traversal](backtracking_algorithm.assets/preorder_find_nodes.png)
![Search for nodes in preorder traversal](backtracking_algorithm.assets/preorder_find_nodes.png)
## Trial and retreat
## Attempt and Backtrack
**It is called a backtracking algorithm because it uses a "trial" and "retreat" strategy when searching the solution space**. During the search, whenever it encounters a state where it can no longer proceed to obtain a satisfying solution, it undoes the previous choice and reverts to the previous state so that other possible choices can be chosen for the next attempt.
**The reason it is called a backtracking algorithm is that it employs "attempt" and "backtrack" strategies when searching the solution space**. When the algorithm encounters a state where it cannot continue forward or cannot find a solution that satisfies the constraints, it will undo the previous choice, return to a previous state, and try other possible choices.
In Example One, visiting each node starts a "trial". And passing a leaf node or the `return` statement to going back to the parent node suggests "retreat".
For Example 1, visiting each node represents an "attempt", while skipping over a leaf node or a function `return` from the parent node represents a "backtrack".
It's worth noting that **retreat is not merely about function returns**. We'll expand slightly on Example One question to explain what it means.
It is worth noting that **backtracking is not limited to function returns alone**. To illustrate this, let's extend Example 1 slightly.
!!! question "Example Two"
!!! question "Example 2"
In a binary tree, search for all nodes with a value of $7$ and for all matching nodes, **please return the paths from the root node to that node**.
In a binary tree, search all nodes with value $7$, **and return the paths from the root node to these nodes**.
Based on the code from Example One, we need to use a list called `path` to record the visited node paths. When a node with a value of $7$ is reached, we copy `path` and add it to the result list `res`. After the traversal, `res` holds all the solutions. The code is as shown:
Based on the code from Example 1, we need to use a list `path` to record the visited node path. When we reach a node with value $7$, we copy `path` and add it to the result list `res`. After traversal is complete, `res` contains all the solutions. The code is as follows:
```src
[file]{preorder_traversal_ii_compact}-[class]{}-[func]{pre_order}
```
In each "trial", we record the path by adding the current node to `path`. Whenever we need to "retreat", we pop the node from `path` **to restore the state prior to this failed attempt**.
In each "attempt", we record the path by adding the current node to `path`; before "backtracking", we need to remove the node from `path`, **to restore the state before this attempt**.
By observing the process shown in the figure below, **the trial is like "advancing", and retreat is like "undoing"**. The later pairs can be seen as a reverse operation to their counterpart.
Observing the process shown in the following figure, **we can understand attempt and backtrack as "advance" and "undo"**, two operations that are the reverse of each other.
=== "<1>"
![Trying and retreating](backtracking_algorithm.assets/preorder_find_paths_step1.png)
![Attempt and backtrack](backtracking_algorithm.assets/preorder_find_paths_step1.png)
=== "<2>"
![preorder_find_paths_step2](backtracking_algorithm.assets/preorder_find_paths_step2.png)
@@ -71,49 +71,49 @@ By observing the process shown in the figure below, **the trial is like "advanci
=== "<11>"
![preorder_find_paths_step11](backtracking_algorithm.assets/preorder_find_paths_step11.png)
## Prune
## Pruning
Complex backtracking problems usually involve one or more constraints, **which are often used for "pruning"**.
Complex backtracking problems usually contain one or more constraints. **Constraints can typically be used for "pruning"**.
!!! question "Example Three"
!!! question "Example 3"
In a binary tree, search for all nodes with a value of $7$ and return the paths from the root to these nodes, **with restriction that the paths do not contain nodes with a value of $3$**.
In a binary tree, search all nodes with value $7$ and return the paths from the root node to these nodes, **but require that the paths do not contain nodes with value $3$**.
To meet the above constraints, **we need to add a pruning operation**: during the search process, if a node with a value of $3$ is encountered, it aborts further searching down through the path immediately. The code is as shown:
To satisfy the above constraints, **we need to add pruning operations**: during the search process, if we encounter a node with value $3$, we return early and do not continue searching. The code is as follows:
```src
[file]{preorder_traversal_iii_compact}-[class]{}-[func]{pre_order}
```
"Pruning" is a very vivid noun. As shown in the figure below, in the search process, **we "cut off" the search branches that do not meet the constraints**. It avoids further unnecessary attempts, thus enhances the search efficiency.
"Pruning" is a vivid term. As shown in the following figure, during the search process, **we "prune" search branches that do not satisfy the constraints**, avoiding many meaningless attempts and thus improving search efficiency.
![Pruning based on constraints](backtracking_algorithm.assets/preorder_find_constrained_paths.png)
![Pruning according to constraints](backtracking_algorithm.assets/preorder_find_constrained_paths.png)
## Framework code
## Framework Code
Now, let's try to distill the main framework of "trial, retreat, and prune" from backtracking to enhance the code's universality.
Next, we attempt to extract the main framework of backtracking's "attempt, backtrack, and pruning", to improve code generality.
In the following framework code, `state` represents the current state of the problem, `choices` represents the choices available under the current state:
In the following framework code, `state` represents the current state of the problem, and `choices` represents the choices available in the current state:
=== "Python"
```python title=""
def backtrack(state: State, choices: list[choice], res: list[state]):
"""Backtracking algorithm framework"""
# Check if it's a solution
# Check if it is a solution
if is_solution(state):
# Record the solution
record_solution(state, res)
# Stop searching
return
# Iterate through all choices
# Traverse all choices
for choice in choices:
# Prune: check if the choice is valid
# Pruning: check if the choice is valid
if is_valid(state, choice):
# Trial: make a choice, update the state
# Attempt: make a choice and update the state
make_choice(state, choice)
backtrack(state, choices, res)
# Retreat: undo the choice, revert to the previous state
# Backtrack: undo the choice and restore to the previous state
undo_choice(state, choice)
```
@@ -122,21 +122,21 @@ In the following framework code, `state` represents the current state of the pro
```cpp title=""
/* Backtracking algorithm framework */
void backtrack(State *state, vector<Choice *> &choices, vector<State *> &res) {
// Check if it's a solution
// Check if it is a solution
if (isSolution(state)) {
// Record the solution
recordSolution(state, res);
// Stop searching
return;
}
// Iterate through all choices
// Traverse all choices
for (Choice choice : choices) {
// Prune: check if the choice is valid
// Pruning: check if the choice is valid
if (isValid(state, choice)) {
// Trial: make a choice, update the state
// Attempt: make a choice and update the state
makeChoice(state, choice);
backtrack(state, choices, res);
// Retreat: undo the choice, revert to the previous state
// Backtrack: undo the choice and restore to the previous state
undoChoice(state, choice);
}
}
@@ -148,21 +148,21 @@ In the following framework code, `state` represents the current state of the pro
```java title=""
/* Backtracking algorithm framework */
void backtrack(State state, List<Choice> choices, List<State> res) {
// Check if it's a solution
// Check if it is a solution
if (isSolution(state)) {
// Record the solution
recordSolution(state, res);
// Stop searching
return;
}
// Iterate through all choices
// Traverse all choices
for (Choice choice : choices) {
// Prune: check if the choice is valid
// Pruning: check if the choice is valid
if (isValid(state, choice)) {
// Trial: make a choice, update the state
// Attempt: make a choice and update the state
makeChoice(state, choice);
backtrack(state, choices, res);
// Retreat: undo the choice, revert to the previous state
// Backtrack: undo the choice and restore to the previous state
undoChoice(state, choice);
}
}
@@ -174,21 +174,21 @@ In the following framework code, `state` represents the current state of the pro
```csharp title=""
/* Backtracking algorithm framework */
void Backtrack(State state, List<Choice> choices, List<State> res) {
// Check if it's a solution
// Check if it is a solution
if (IsSolution(state)) {
// Record the solution
RecordSolution(state, res);
// Stop searching
return;
}
// Iterate through all choices
// Traverse all choices
foreach (Choice choice in choices) {
// Prune: check if the choice is valid
// Pruning: check if the choice is valid
if (IsValid(state, choice)) {
// Trial: make a choice, update the state
// Attempt: make a choice and update the state
MakeChoice(state, choice);
Backtrack(state, choices, res);
// Retreat: undo the choice, revert to the previous state
// Backtrack: undo the choice and restore to the previous state
UndoChoice(state, choice);
}
}
@@ -200,21 +200,21 @@ In the following framework code, `state` represents the current state of the pro
```go title=""
/* Backtracking algorithm framework */
func backtrack(state *State, choices []Choice, res *[]State) {
// Check if it's a solution
// Check if it is a solution
if isSolution(state) {
// Record the solution
recordSolution(state, res)
// Stop searching
return
}
// Iterate through all choices
// Traverse all choices
for _, choice := range choices {
// Prune: check if the choice is valid
// Pruning: check if the choice is valid
if isValid(state, choice) {
// Trial: make a choice, update the state
// Attempt: make a choice and update the state
makeChoice(state, choice)
backtrack(state, choices, res)
// Retreat: undo the choice, revert to the previous state
// Backtrack: undo the choice and restore to the previous state
undoChoice(state, choice)
}
}
@@ -226,21 +226,21 @@ In the following framework code, `state` represents the current state of the pro
```swift title=""
/* Backtracking algorithm framework */
func backtrack(state: inout State, choices: [Choice], res: inout [State]) {
// Check if it's a solution
// Check if it is a solution
if isSolution(state: state) {
// Record the solution
recordSolution(state: state, res: &res)
// Stop searching
return
}
// Iterate through all choices
// Traverse all choices
for choice in choices {
// Prune: check if the choice is valid
// Pruning: check if the choice is valid
if isValid(state: state, choice: choice) {
// Trial: make a choice, update the state
// Attempt: make a choice and update the state
makeChoice(state: &state, choice: choice)
backtrack(state: &state, choices: choices, res: &res)
// Retreat: undo the choice, revert to the previous state
// Backtrack: undo the choice and restore to the previous state
undoChoice(state: &state, choice: choice)
}
}
@@ -252,21 +252,21 @@ In the following framework code, `state` represents the current state of the pro
```javascript title=""
/* Backtracking algorithm framework */
function backtrack(state, choices, res) {
// Check if it's a solution
// Check if it is a solution
if (isSolution(state)) {
// Record the solution
recordSolution(state, res);
// Stop searching
return;
}
// Iterate through all choices
// Traverse all choices
for (let choice of choices) {
// Prune: check if the choice is valid
// Pruning: check if the choice is valid
if (isValid(state, choice)) {
// Trial: make a choice, update the state
// Attempt: make a choice and update the state
makeChoice(state, choice);
backtrack(state, choices, res);
// Retreat: undo the choice, revert to the previous state
// Backtrack: undo the choice and restore to the previous state
undoChoice(state, choice);
}
}
@@ -278,21 +278,21 @@ In the following framework code, `state` represents the current state of the pro
```typescript title=""
/* Backtracking algorithm framework */
function backtrack(state: State, choices: Choice[], res: State[]): void {
// Check if it's a solution
// Check if it is a solution
if (isSolution(state)) {
// Record the solution
recordSolution(state, res);
// Stop searching
return;
}
// Iterate through all choices
// Traverse all choices
for (let choice of choices) {
// Prune: check if the choice is valid
// Pruning: check if the choice is valid
if (isValid(state, choice)) {
// Trial: make a choice, update the state
// Attempt: make a choice and update the state
makeChoice(state, choice);
backtrack(state, choices, res);
// Retreat: undo the choice, revert to the previous state
// Backtrack: undo the choice and restore to the previous state
undoChoice(state, choice);
}
}
@@ -304,21 +304,21 @@ In the following framework code, `state` represents the current state of the pro
```dart title=""
/* Backtracking algorithm framework */
void backtrack(State state, List<Choice>, List<State> res) {
// Check if it's a solution
// Check if it is a solution
if (isSolution(state)) {
// Record the solution
recordSolution(state, res);
// Stop searching
return;
}
// Iterate through all choices
// Traverse all choices
for (Choice choice in choices) {
// Prune: check if the choice is valid
// Pruning: check if the choice is valid
if (isValid(state, choice)) {
// Trial: make a choice, update the state
// Attempt: make a choice and update the state
makeChoice(state, choice);
backtrack(state, choices, res);
// Retreat: undo the choice, revert to the previous state
// Backtrack: undo the choice and restore to the previous state
undoChoice(state, choice);
}
}
@@ -330,21 +330,21 @@ In the following framework code, `state` represents the current state of the pro
```rust title=""
/* Backtracking algorithm framework */
fn backtrack(state: &mut State, choices: &Vec<Choice>, res: &mut Vec<State>) {
// Check if it's a solution
// Check if it is a solution
if is_solution(state) {
// Record the solution
record_solution(state, res);
// Stop searching
return;
}
// Iterate through all choices
// Traverse all choices
for choice in choices {
// Prune: check if the choice is valid
// Pruning: check if the choice is valid
if is_valid(state, choice) {
// Trial: make a choice, update the state
// Attempt: make a choice and update the state
make_choice(state, choice);
backtrack(state, choices, res);
// Retreat: undo the choice, revert to the previous state
// Backtrack: undo the choice and restore to the previous state
undo_choice(state, choice);
}
}
@@ -356,21 +356,21 @@ In the following framework code, `state` represents the current state of the pro
```c title=""
/* Backtracking algorithm framework */
void backtrack(State *state, Choice *choices, int numChoices, State *res, int numRes) {
// Check if it's a solution
// Check if it is a solution
if (isSolution(state)) {
// Record the solution
recordSolution(state, res, numRes);
// Stop searching
return;
}
// Iterate through all choices
// Traverse all choices
for (int i = 0; i < numChoices; i++) {
// Prune: check if the choice is valid
// Pruning: check if the choice is valid
if (isValid(state, &choices[i])) {
// Trial: make a choice, update the state
// Attempt: make a choice and update the state
makeChoice(state, &choices[i]);
backtrack(state, choices, numChoices, res, numRes);
// Retreat: undo the choice, revert to the previous state
// Backtrack: undo the choice and restore to the previous state
undoChoice(state, &choices[i]);
}
}
@@ -382,21 +382,21 @@ In the following framework code, `state` represents the current state of the pro
```kotlin title=""
/* Backtracking algorithm framework */
fun backtrack(state: State?, choices: List<Choice?>, res: List<State?>?) {
// Check if it's a solution
// Check if it is a solution
if (isSolution(state)) {
// Record the solution
recordSolution(state, res)
// Stop searching
return
}
// Iterate through all choices
// Traverse all choices
for (choice in choices) {
// Prune: check if the choice is valid
// Pruning: check if the choice is valid
if (isValid(state, choice)) {
// Trial: make a choice, update the state
// Attempt: make a choice and update the state
makeChoice(state, choice)
backtrack(state, choices, res)
// Retreat: undo the choice, revert to the previous state
// Backtrack: undo the choice and restore to the previous state
undoChoice(state, choice)
}
}
@@ -406,7 +406,27 @@ In the following framework code, `state` represents the current state of the pro
=== "Ruby"
```ruby title=""
### Backtracking algorithm framework ###
def backtrack(state, choices, res)
# Check if it is a solution
if is_solution?(state)
# Record the solution
record_solution(state, res)
return
end
# Traverse all choices
for choice in choices
# Pruning: check if the choice is valid
if is_valid?(state, choice)
# Attempt: make a choice and update the state
make_choice(state, choice)
backtrack(state, choices, res)
# Backtrack: undo the choice and restore to the previous state
undo_choice(state, choice)
end
end
end
```
=== "Zig"
@@ -415,75 +435,75 @@ In the following framework code, `state` represents the current state of the pro
```
Now, we are able to solve Example Three using the framework code. The `state` is the node traversal path, `choices` are the current node's left and right children, and the result `res` is the list of paths:
Next, we solve Example 3 based on the framework code. The state `state` is the node traversal path, the choices `choices` are the left and right child nodes of the current node, and the result `res` is a list of paths:
```src
[file]{preorder_traversal_iii_template}-[class]{}-[func]{backtrack}
```
As per the requirements, after finding a node with a value of $7$, the search should continue. **As a result, the `return` statement after recording the solution should be removed**. The figure below compares the search processes with and without retaining the `return` statement.
As per the problem statement, we should continue searching after finding a node with value $7$. **Therefore, we need to remove the `return` statement after recording the solution**. The following figure compares the search process with and without the `return` statement.
![Comparison of retaining and removing the return in the search process](backtracking_algorithm.assets/backtrack_remove_return_or_not.png)
![Comparison of search process with and without return statement](backtracking_algorithm.assets/backtrack_remove_return_or_not.png)
Compared to the implementation based on pre-order traversal, the code using the backtracking algorithm framework seems verbose. However, it has better universality. In fact, **many backtracking problems can be solved within this framework**. We just need to define `state` and `choices` according to the specific problem and implement the methods in the framework.
Compared to code based on preorder traversal, code based on the backtracking algorithm framework appears more verbose, but has better generality. In fact, **many backtracking problems can be solved within this framework**. We only need to define `state` and `choices` for the specific problem and implement each method in the framework.
## Common terminology
## Common Terminology
To analyze algorithmic problems more clearly, we summarize the meanings of commonly used terminology in backtracking algorithms and provide corresponding examples from Example Three as shown in the table below.
To analyze algorithmic problems more clearly, we summarize the meanings of common terminology used in backtracking algorithms and provide corresponding examples from Example 3, as shown in the following table.
<p align="center"> Table <id> &nbsp; Common backtracking algorithm terminology </p>
<p align="center"> Table <id> &nbsp; Common Backtracking Algorithm Terminology </p>
| Term | Definition | Example Three |
| --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
| Solution | A solution is an answer that satisfies specific conditions of the problem, which may have one or more | All paths from the root node to node $7$ that meet the constraint |
| Constraint | Constraints are conditions in the problem that limit the feasibility of solutions, often used for pruning | Paths do not contain node $3$ |
| State | State represents the situation of the problem at a certain moment, including choices made | Current visited node path, i.e., `path` node list |
| Trial | A trial is the process of exploring the solution space based on available choices, including making choices, updating the state, and checking if it's a solution | Recursively visiting left (right) child nodes, adding nodes to `path`, checking if the node's value is $7$ |
| Retreat | Retreat refers to the action of undoing previous choices and returning to the previous state when encountering states that do not meet the constraints | When passing leaf nodes, ending node visits, encountering nodes with a value of $3$, terminating the search, and the recursion function returns |
| Prune | Prune is a method to avoid meaningless search paths based on the characteristics and constraints of the problem, which can enhance search efficiency | When encountering a node with a value of $3$, no further search is required |
| Term | Definition | Example 3 |
| ------------------------- | ---------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- |
| Solution (solution) | A solution is an answer that satisfies the specific conditions of a problem; there may be one or more solutions | All paths from root to nodes with value $7$ that satisfy the constraint |
| Constraint (constraint) | A constraint is a condition in the problem that limits the feasibility of solutions, typically used for pruning | Paths do not contain nodes with value $3$ |
| State (state) | State represents the situation of a problem at a certain moment, including the choices already made | The currently visited node path, i.e., the `path` list of nodes |
| Attempt (attempt) | An attempt is the process of exploring the solution space according to available choices, including making choices, updating state, and checking if it is a solution | Recursively visit left (right) child nodes, add nodes to `path`, check if node value is $7$ |
| Backtrack (backtracking) | Backtracking refers to undoing previous choices and returning to a previous state when encountering a state that does not satisfy constraints | Stop searching when passing over leaf nodes, ending node visits, or encountering nodes with value $3$; function returns |
| Pruning (pruning) | Pruning is a method of avoiding meaningless search paths according to problem characteristics and constraints, which can improve search efficiency | When encountering a node with value $3$, do not continue searching |
!!! tip
Concepts like problems, solutions, states, etc., are universal, and are involved in divide and conquer, backtracking, dynamic programming, and greedy algorithms, among others.
The concepts of problem, solution, state, etc. are universal and are involved in divide-and-conquer, backtracking, dynamic programming, greedy and other algorithms.
## Advantages and limitations
## Advantages and Limitations
The backtracking algorithm is essentially a depth-first search algorithm that attempts all possible solutions until a satisfying solution is found. The advantage of this method is that it can find all possible solutions, and with reasonable pruning operations, it can be highly efficient.
The backtracking algorithm is essentially a depth-first search algorithm that tries all possible solutions until it finds one that satisfies the conditions. The advantage of this approach is that it can find all possible solutions, and with reasonable pruning operations, it achieves high efficiency.
However, when dealing with large-scale or complex problems, **the running efficiency of backtracking algorithm may not be acceptable**.
However, when dealing with large-scale or complex problems, **the running efficiency of the backtracking algorithm may be unacceptable**.
- **Time complexity**: Backtracking algorithms usually need to traverse all possible states in the state space, which can reach exponential or factorial time complexity.
- **Space complexity**: In recursive calls, it is necessary to save the current state (such as paths, auxiliary variables for pruning, etc.). When the depth is very large, the space need may become significantly bigger.
- **Time**: The backtracking algorithm usually needs to traverse all possibilities in the solution space, and the time complexity can reach exponential or factorial order.
- **Space**: During recursive calls, the current state needs to be saved (such as paths, auxiliary variables used for pruning, etc.), and when the depth is large, the space requirement can become very large.
Even so, **backtracking remains the best solution for certain search problems and constraint satisfaction problems**. For these problems, there is no way to predict which choices can generate valid solutions. We have to traverse all possible choices. In this case, **the key is about how to optimize the efficiency**. There are two common efficiency optimization methods.
Nevertheless, **the backtracking algorithm is still the best solution for certain search problems and constraint satisfaction problems**. For these problems, since we cannot predict which choices will generate valid solutions, we must traverse all possible choices. In this case, **the key is how to optimize efficiency**. There are two common efficiency optimization methods.
- **Prune**: Avoid searching paths that definitely will not produce a solution, thus saving time and space.
- **Heuristic search**: Introduce some strategies or estimates during the search process to prioritize the paths that are most likely to produce valid solutions.
- **Pruning**: Avoid searching paths that are guaranteed not to produce solutions, thereby saving time and space.
- **Heuristic search**: Introduce certain strategies or estimation values during the search process to prioritize searching paths that are most likely to produce valid solutions.
## Typical backtracking problems
## Typical Backtracking Examples
Backtracking algorithms can be used to solve many search problems, constraint satisfaction problems, and combinatorial optimization problems.
The backtracking algorithm can be used to solve many search problems, constraint satisfaction problems, and combinatorial optimization problems.
**Search problems**: The goal of these problems is to find solutions that meet specific conditions.
**Search problems**: The goal of these problems is to find solutions that satisfy specific conditions.
- Full permutation problem: Given a set, find all possible permutations and combinations of it.
- Subset sum problem: Given a set and a target sum, find all subsets of the set that sum to the target.
- Tower of Hanoi problem: Given three rods and a series of different-sized discs, the goal is to move all the discs from one rod to another, moving only one disc at a time, and never placing a larger disc on a smaller one.
- Permutation problem: Given a set, find all possible permutations and combinations.
- Subset sum problem: Given a set and a target sum, find all subsets in the set whose elements sum to the target.
- Tower of Hanoi: Given three pegs and a series of disks of different sizes, move all disks from one peg to another, moving only one disk at a time, and never placing a larger disk on a smaller disk.
**Constraint satisfaction problems**: The goal of these problems is to find solutions that satisfy all the constraints.
**Constraint satisfaction problems**: The goal of these problems is to find solutions that satisfy all constraints.
- $n$ queens: Place $n$ queens on an $n \times n$ chessboard so that they do not attack each other.
- Sudoku: Fill a $9 \times 9$ grid with the numbers $1$ to $9$, ensuring that the numbers do not repeat in each row, each column, and each $3 \times 3$ subgrid.
- Graph coloring problem: Given an undirected graph, color each vertex with the fewest possible colors so that adjacent vertices have different colors.
- N-Queens: Place $n$ queens on an $n \times n$ chessboard such that they do not attack each other.
- Sudoku: Fill numbers $1$ to $9$ in a $9 \times 9$ grid such that each row, column, and $3 \times 3$ subgrid contains no repeated digits.
- Graph coloring: Given an undirected graph, color each vertex with the minimum number of colors such that adjacent vertices have different colors.
**Combinatorial optimization problems**: The goal of these problems is to find the optimal solution within a combination space that meets certain conditions.
**Combinatorial optimization problems**: The goal of these problems is to find an optimal solution that satisfies certain conditions in a combinatorial space.
- 0-1 knapsack problem: Given a set of items and a backpack, each item has a certain value and weight. The goal is to choose items to maximize the total value within the backpack's capacity limit.
- Traveling salesman problem: In a graph, starting from one point, visit all other points exactly once and then return to the starting point, seeking the shortest path.
- Maximum clique problem: Given an undirected graph, find the largest complete subgraph, i.e., a subgraph where any two vertices are connected by an edge.
- 0-1 Knapsack: Given a set of items and a knapsack, each item has a value and weight. Under the knapsack capacity constraint, select items to maximize total value.
- Traveling Salesman Problem: Starting from a point in a graph, visit all other points exactly once and return to the starting point, finding the shortest path.
- Maximum Clique: Given an undirected graph, find the largest complete subgraph, i.e., a subgraph where any two vertices are connected by an edge.
Please note that for many combinatorial optimization problems, backtracking is not the optimal solution.
Note that for many combinatorial optimization problems, backtracking is not the optimal solution.
- The 0-1 knapsack problem is usually solved using dynamic programming to achieve higher time efficiency.
- The traveling salesman is a well-known NP-Hard problem, commonly solved using genetic algorithms and ant colony algorithms, among others.
- The maximum clique problem is a classic problem in graph theory, which can be solved using greedy algorithms and other heuristic methods.
- The 0-1 Knapsack problem is usually solved using dynamic programming to achieve higher time efficiency.
- The Traveling Salesman Problem is a famous NP-Hard problem; common solutions include genetic algorithms and ant colony algorithms.
- The Maximum Clique problem is a classical problem in graph theory and can be solved using heuristic algorithms such as greedy algorithms.