迭代加深搜索(IDDFS)
概念讲解
什么是 IDDFS?
IDDFS 是一种限制搜索深度的 DFS,逐步增加深度限制。
核心思想
结合了 DFS 的空间优势和 BFS 的最优性。
实现
123456789101112131415161718192021222324bool found;
void dfs(int state, int depth, int limit) {
if (found) return;
if (depth > limit) return;
if (isGoal(state)) {
found = true;
return;
}
for (int nextState : getNeighbors(state)) {
dfs(nextState, depth + 1, limit);
}
}
int iddfs(int start, int maxDepth) {
for (int limit = 0; limit <= maxDepth; limit++) {
found = false;
dfs(start, 0, limit);
if (found) return limit;
}
return -1;
}适用场景
- 搜索空间很大
- 最优解深度较浅
- 内存有限
考点分析
初赛考查方式
- 选择题: IDDFS 的概念
- 程序阅读: 理解 IDDFS
- 编程题: IDDFS 应用
常见题型
- 最优解搜索
- 深度限制搜索
例题精讲
例题 1:IDDFS
题目: 使用 IDDFS 求解问题。
解答:
123456789101112131415161718192021222324252627282930313233343536373839404142#include <iostream>
using namespace std;
bool found;
bool isGoal(int state) {
// 判断是否是目标状态
return false;
}
void dfs(int state, int depth, int limit) {
if (found) return;
if (depth > limit) return;
if (isGoal(state)) {
found = true;
return;
}
// 扩展邻居状态
for (int i = 0; i < 4; i++) {
int nextState = state; // 根据操作生成新状态
dfs(nextState, depth + 1, limit);
}
}
int main() {
int start, maxDepth;
cin >> start >> maxDepth;
for (int limit = 0; limit <= maxDepth; limit++) {
found = false;
dfs(start, 0, limit);
if (found) {
cout << limit << endl;
return 0;
}
}
cout << -1 << endl;
return 0;
}练习题
- 洛谷 P1379 八数码难题
查看答案
思路:IDA* 算法,使用启发式函数剪枝。
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768#include <iostream>
#include <cmath>
using namespace std;
int dx[] = {0, 0, 1, -1};
int dy[] = {1, -1, 0, 0};
int target[3][3] = {{1, 2, 3}, {8, 0, 4}, {7, 6, 5}};
int a[3][3];
int maxDepth;
int heuristic() {
int dist = 0;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (a[i][j] != 0) {
int val = a[i][j] - 1;
dist += abs(i - val / 3) + abs(j - val % 3);
}
}
}
return dist;
}
bool dfs(int x, int y, int depth, int last) {
int h = heuristic();
if (h == 0) return true;
if (depth + h > maxDepth) return false;
for (int i = 0; i < 4; i++) {
if (i == (last ^ 1)) continue;
int nx = x + dx[i], ny = y + dy[i];
if (nx < 0 || nx >= 3 || ny < 0 || ny >= 3) continue;
swap(a[x][y], a[nx][ny]);
if (dfs(nx, ny, depth + 1, i)) return true;
swap(a[x][y], a[nx][ny]);
}
return false;
}
int main() {
int sx, sy;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
char c;
cin >> c;
if (c == 'x') {
a[i][j] = 0;
sx = i;
sy = j;
} else {
a[i][j] = c - '0';
}
}
}
for (maxDepth = 0; maxDepth <= 30; maxDepth++) {
if (dfs(sx, sy, 0, -1)) {
cout << maxDepth << endl;
return 0;
}
}
cout << -1 << endl;
return 0;
}- 洛谷 P2324 [SCOI2005] 骑士精神
查看答案
思路:IDA* 算法。
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677#include <iostream>
using namespace std;
int target[5][5] = {
{1, 1, 1, 1, 1},
{0, 1, 1, 1, 1},
{0, 0, 2, 1, 1},
{0, 0, 0, 0, 1},
{0, 0, 0, 0, 0}
};
int a[5][5];
int maxDepth;
int dx[] = {-2, -2, -1, -1, 1, 1, 2, 2};
int dy[] = {-1, 1, -2, 2, -2, 2, -1, 1};
int heuristic() {
int cnt = 0;
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
if (a[i][j] != target[i][j]) cnt++;
}
}
return cnt;
}
bool dfs(int x, int y, int depth) {
int h = heuristic();
if (h == 0) return true;
if (depth + h > maxDepth) return false;
for (int i = 0; i < 8; i++) {
int nx = x + dx[i], ny = y + dy[i];
if (nx < 0 || nx >= 5 || ny < 0 || ny >= 5) continue;
swap(a[x][y], a[nx][ny]);
if (dfs(nx, ny, depth + 1)) return true;
swap(a[x][y], a[nx][ny]);
}
return false;
}
int main() {
int T;
cin >> T;
while (T--) {
int sx, sy;
for (int i = 0; i < 5; i++) {
string s;
cin >> s;
for (int j = 0; j < 5; j++) {
if (s[j] == '*') {
a[i][j] = 2;
sx = i;
sy = j;
} else {
a[i][j] = s[j] - '0';
}
}
}
bool found = false;
for (maxDepth = 0; maxDepth <= 15; maxDepth++) {
if (dfs(sx, sy, 0)) {
cout << maxDepth << endl;
found = true;
break;
}
}
if (!found) cout << -1 << endl;
}
return 0;
}- 洛谷 P1441 砝码称重
查看答案
思路:枚举去掉的砝码,然后 DP 求解。
12345678910111213141516171819202122232425262728293031323334353637#include <iostream>
using namespace std;
int main() {
int n, m;
cin >> n >> m;
int a[n];
for (int i = 0; i < n; i++) cin >> a[i];
int ans = 0;
for (int mask = 0; mask < (1 << n); mask++) {
if (__builtin_popcount(mask) != n - m) continue;
bool dp[2005] = {false};
dp[0] = true;
for (int i = 0; i < n; i++) {
if (mask & (1 << i)) continue;
for (int j = 2000; j >= a[i]; j--) {
if (dp[j - a[i]]) dp[j] = true;
}
}
int cnt = 0;
for (int i = 1; i <= 2000; i++) {
if (dp[i]) cnt++;
}
ans = max(ans, cnt);
}
cout << ans << endl;
return 0;
}易错点
⚠️ 注意:
- IDDFS 是 DFS 和 BFS 的结合
- 逐步增加深度限制
- IDDFS 通常比 BFS 更省内存
- 适用场景有限