vault backup: 2026-06-10 11:19:43
This commit is contained in:
+85
-44
@@ -78,17 +78,26 @@ flowchart TD
|
||||
|
||||
### 五、回溯法一般框架
|
||||
|
||||
```plaintext
|
||||
void backtrack(int t) {
|
||||
```cpp
|
||||
#include <vector>
|
||||
using namespace std;
|
||||
|
||||
// 回溯法框架
|
||||
// t: 当前搜索深度(第几个决策)
|
||||
// n: 问题规模(总共需要做的决策数)
|
||||
// x: 当前解向量
|
||||
void backtrack(int t, int n, vector<int>& x) {
|
||||
if (t > n)
|
||||
output(x); // 到达叶节点,输出解
|
||||
else {
|
||||
for (int i = f(n,t); i <= g(n,t); i++) {
|
||||
x[t] = h(i); // 第t个位置尝试第i种选择
|
||||
if (constraint(t) && bound(t))
|
||||
backtrack(t+1); // 满足约束,继续深入
|
||||
// 否则剪枝,回退(x[t]会被下次循环覆盖)
|
||||
}
|
||||
// output(x); // 到达叶节点,输出解
|
||||
return;
|
||||
// f(n,t) 和 g(n,t) 为第t个位置可选值的范围
|
||||
// h(i) 将第i个候选值赋给x[t]
|
||||
// constraint(t) 为约束函数,bound(t) 为限界函数
|
||||
for (int i = 1; i <= n; i++) {
|
||||
x[t] = i; // 第t个位置尝试第i种选择
|
||||
if (/* constraint(t) && */ /* bound(t) */ true)
|
||||
backtrack(t + 1, n, x); // 满足约束,继续深入
|
||||
// 否则剪枝,回退(x[t]会被下次循环覆盖)
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -116,23 +125,40 @@ void backtrack(int t) {
|
||||
|
||||
**时间复杂度**:最坏 O(mⁿ),四色问题为 O(4ⁿ)
|
||||
|
||||
```plaintext
|
||||
function graphColoring(graph, m, colors, vertex):
|
||||
if vertex == n:
|
||||
printSolution(colors) // 所有顶点着色完成
|
||||
return
|
||||
```cpp
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
using namespace std;
|
||||
|
||||
for c = 1 to m:
|
||||
colors[vertex] = c // 尝试颜色c
|
||||
if isSafe(graph, colors, vertex):
|
||||
graphColoring(graph, m, colors, vertex + 1)
|
||||
colors[vertex] = 0 // 回溯
|
||||
// 判断将 vertex 着色为 colors[vertex] 是否安全
|
||||
bool isSafe(vector<vector<int>>& graph, vector<int>& colors, int vertex) {
|
||||
int n = graph.size();
|
||||
for (int v = 0; v < n; v++) {
|
||||
if (graph[vertex][v] && colors[v] == colors[vertex])
|
||||
return false; // 相邻顶点颜色相同,不安全
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function isSafe(graph, colors, vertex):
|
||||
for each neighbor v of vertex:
|
||||
if colors[v] == colors[vertex]:
|
||||
return false
|
||||
return true
|
||||
// 图着色回溯算法
|
||||
// graph: 邻接矩阵, m: 颜色数, colors: 着色方案, vertex: 当前处理的顶点
|
||||
void graphColoring(vector<vector<int>>& graph, int m, vector<int>& colors, int vertex) {
|
||||
int n = graph.size();
|
||||
if (vertex == n) {
|
||||
// 所有顶点着色完成,输出解
|
||||
for (int i = 0; i < n; i++)
|
||||
cout << colors[i] << " ";
|
||||
cout << endl;
|
||||
return;
|
||||
}
|
||||
|
||||
for (int c = 1; c <= m; c++) {
|
||||
colors[vertex] = c; // 尝试颜色c
|
||||
if (isSafe(graph, colors, vertex))
|
||||
graphColoring(graph, m, colors, vertex + 1);
|
||||
colors[vertex] = 0; // 回溯
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```mermaid
|
||||
@@ -173,29 +199,44 @@ flowchart TD
|
||||
- 检查列冲突和对角线冲突
|
||||
- 冲突则剪枝
|
||||
|
||||
```plaintext
|
||||
function solveNQueens(board, row, n):
|
||||
if row == n:
|
||||
printBoard(board)
|
||||
return
|
||||
```cpp
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
using namespace std;
|
||||
|
||||
for col = 0 to n-1:
|
||||
if isSafe(board, row, col, n):
|
||||
board[row][col] = "Q" // 放置皇后
|
||||
solveNQueens(board, row + 1, n)
|
||||
board[row][col] = "." // 回溯
|
||||
|
||||
function isSafe(board, row, col, n):
|
||||
// 判断在 (row, col) 放置皇后是否安全
|
||||
bool isSafe(vector<string>& board, int row, int col, int n) {
|
||||
// 检查同一列
|
||||
for i = 0 to row-1:
|
||||
if board[i][col] == "Q": return false
|
||||
for (int i = 0; i < row; i++)
|
||||
if (board[i][col] == 'Q') return false;
|
||||
// 检查左上对角线
|
||||
for i = row-1, j = col-1; i >= 0 && j >= 0; i--, j--:
|
||||
if board[i][j] == "Q": return false
|
||||
for (int i = row - 1, j = col - 1; i >= 0 && j >= 0; i--, j--)
|
||||
if (board[i][j] == 'Q') return false;
|
||||
// 检查右上对角线
|
||||
for i = row-1, j = col+1; i >= 0 && j < n; i--, j++:
|
||||
if board[i][j] == "Q": return false
|
||||
return true
|
||||
for (int i = row - 1, j = col + 1; i >= 0 && j < n; i--, j++)
|
||||
if (board[i][j] == 'Q') return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
// N皇后回溯算法
|
||||
// board: 棋盘, row: 当前处理的行, n: 棋盘大小
|
||||
void solveNQueens(vector<string>& board, int row, int n) {
|
||||
if (row == n) {
|
||||
// 输出一个解
|
||||
for (int i = 0; i < n; i++)
|
||||
cout << board[i] << endl;
|
||||
cout << endl;
|
||||
return;
|
||||
}
|
||||
|
||||
for (int col = 0; col < n; col++) {
|
||||
if (isSafe(board, row, col, n)) {
|
||||
board[row][col] = 'Q'; // 放置皇后
|
||||
solveNQueens(board, row + 1, n);
|
||||
board[row][col] = '.'; // 回溯
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**解释**:N皇后是经典的回溯应用。由于每行只放一个皇后,解空间是排列树。剪枝函数检查列冲突和两条对角线冲突,大幅减少搜索空间。
|
||||
|
||||
Reference in New Issue
Block a user