Files
Data-Structure/Algorithm/BackTracking/readme.md
2025-08-30 21:59:50 +08:00

81 lines
2.2 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

回溯法Backtracking是一种**系统地枚举所有可能解**的方法,通常用于解决**组合、排列、约束满足等问题**。它的核心思想是:在搜索问题的解空间时,如果发现当前部分解无法得到最终解,就**立即放弃(回溯)**,避免无谓的计算。
我给你拆开讲:
---
### 1⃣ 基本思路
1. 从问题的初始状态开始,尝试每一种可能的选择。
2. 对于每一种选择:
* 判断是否符合条件(约束)。
* 如果符合,就继续尝试下一步。
* 如果不符合,直接放弃(剪枝)。
3. 当到达最终状态时,把解记录下来。
4. 搜索完当前选择后,撤销选择(回到上一步),尝试其他可能。
这个“尝试→失败→撤销→尝试其他”过程就是“回溯”。
---
### 2⃣ 典型问题
回溯法适合解决这类问题:
* **排列问题**生成1\~n的所有排列。
* **组合问题**从n个元素中选出k个组合。
* **子集问题**:生成所有子集。
* **棋盘类问题**N皇后、数独、填字游戏。
* **约束满足问题**:图着色、八数码问题等。
---
### 3⃣ 模板代码C++示例)
以**N皇后问题**为例:
```cpp
vector<int> queens; // queens[i] = 列号
int n;
bool isValid(int row, int col) {
for(int i = 0; i < row; i++) {
int c = queens[i];
if(c == col || abs(c - col) == row - i)
return false;
}
return true;
}
void backtrack(int row) {
if(row == n) {
// 找到一个解
for(int c : queens) cout << c << " ";
cout << endl;
return;
}
for(int col = 0; col < n; col++) {
if(isValid(row, col)) {
queens.push_back(col); // 选择
backtrack(row + 1); // 递归
queens.pop_back(); // 回溯
}
}
}
```
---
### 4⃣ 总结
* 回溯法是一种**DFS+剪枝**的方法。
* 核心是**选择、约束、递归、撤销**。
* 常用于**枚举问题、组合问题和约束满足问题**。
---
如果你愿意,我可以给你画一张**回溯法搜索树的示意图**,直观理解它是怎么“尝试、失败、回退”的。
你想让我画吗?