暴力枚举与完全搜索
把所有可能都试一遍,逐个检查。简单粗暴有效 —— 关键在会分析、会剪枝。
一、三种形态
| 形态 | 规模 | 怎么枚举 |
|---|---|---|
| 循环枚举 | 看几重循环 | 多重 for,重点是用条件优化掉一层 |
| 子集枚举 | 2ⁿ | 递归"选/不选",或二进制位枚举 |
| 排列枚举 | n! | next_permutation 或手写递归 |
二、互动演示:子集枚举(位枚举)
3 个物品,每个"选或不选",共 2³ = 8 种。点“下一个”,看整数 mask 从 0 数到 7,二进制的每一位 1 就代表选中对应物品。
mask=0 表示空集(一个都不选)。点“下一个”。
三、经典回溯:八皇后复杂度怎么降
| 做法 | 候选规模 |
|---|---|
| 64 格放 8 个,8 层循环 | 64⁸ ≈ 256 万亿 ❌ |
| 每行只放一个(按行精简) | 8⁸ ≈ 1600 万 |
| 再加列 / 斜线剪枝 | 远小于 8⁸ ✅ |
体会"分析的力量":一点点剪枝就能让候选数量断崖式下降。
四、参考代码:八皇后(回溯)
int col[9], ans = 0; // col[r] = 第 r 行皇后所在列
bool ok(int r, int c) {
for (int i = 1; i < r; i++)
// 同列,或同斜线(行差==列差)
if (col[i] == c || abs(col[i] - c) == abs(i - r)) return false;
return true;
}
void dfs(int r) { // 正在放第 r 行
if (r > 8) { ans++; return; }
for (int c = 1; c <= 8; c++)
if (ok(r, c)) { col[r] = c; dfs(r + 1); } // 试一个→往下→自动回溯
}
回溯 = 递归地"试一个 → 往下走 → 不行就退回换下一个"。完全搜索 == 递归回溯。