迭代加深搜索(IDDFS)
💡 核心思想
迭代加深搜索(IDDFS)是一种限制搜索深度的 DFS:从深度 1 开始,逐步增加深度限制,每次在限制深度内做 DFS。它结合了 DFS 的空间优势和 BFS 的最优性保证,特别适合状态空间巨大但最优解深度不大的问题。
IDDFS 是 CSP-S 中处理"最少步数"问题的利器。当 BFS 状态太多爆内存,而普通 DFS 可能陷入无限深搜索时,IDDFS 就是最佳选择。经典应用:埃及分数、骑士精神、八数码问题。记住模板:外层循环增加深度限制,内层 DFS 加深度判断,超过限制就剪枝。
🎯 直觉理解
想象你在一个巨大的迷宫里找出口。BFS 会同时探索所有方向,内存可能爆炸;DFS 可能一条路走到黑永远回不来。IDDFS 的策略是:先只探索深度 1 的范围,找不到再探索深度 2,然后深度 3... 就像你决定"这次最多走 10 步",走不到就回头,下次允许走 11 步。
📝 算法流程
- 设定初始深度限制 maxDepth = 1
- 在 maxDepth 限制下做 DFS
- 如果找到解,返回
- 否则 maxDepth++,重复步骤 2
- DFS 中:如果当前深度 > maxDepth,剪枝返回
$$\text{总节点数} \approx O(b^d) \text{,其中 }b\text{ 为分支因子,}d\text{ 为解深度}$$
📊 复杂度分析
| 指标 | 复杂度 |
|---|---|
| 时间 | $O(b^d)$(与 BFS 同级,但常数更大) |
| 空间 | $O(d)$(仅递归栈) |
💻 参考实现(C++)
C++ (C++17)
#include
using namespace std;
bool found;
int maxDepth;
// 示例:在数字 1~n 中找和为 target 的最少个数(IDDFS 模板)
void dfs(int cur, int depth, int target) {
if (found) return;
if (cur == target) { found = true; return; }
if (depth >= maxDepth) return; // 超过深度限制,剪枝
if (cur > target) return; // 剪枝:已经超过目标
// 尝试加下一个数(分支)
for (int i = 1; i <= 3 && !found; i++) // 每次可以 +1, +2, +3
dfs(cur + i, depth + 1, target);
}
int iddfs(int target) {
for (maxDepth = 1; ; maxDepth++) {
found = false;
dfs(0, 0, target);
if (found) return maxDepth;
}
}
int main() {
cout << iddfs(10) << endl; // 最少 4 步:3+3+3+1
return 0;
} ⚠️ 常见坑点
忘记重置 found 标志——每次深度限制增加前要清零
剪枝条件不够强——IDDFS 效率取决于剪枝质量
与 BFS 混淆——IDDFS 空间更优但时间常数更大
深度限制从 0 还是从 1 开始——通常从 1 开始
📚 相关题目
| 题目 | 来源 | 难度 | 备注 |
|---|---|---|---|
| P2324 骑士精神 | 洛谷 | CSP-S | IDDFS 经典题 |
| P2730 八数码 | 洛谷 | CSP-S | IDDFS / 双向 BFS |
| P1120 小木棍 | 洛谷 | CSP-S | IDDFS + 强剪枝 |