
深度优先搜索每次固定选定一个分支,不断深入,直到达到递归边界才回溯。这种策略带有一定的缺陷,假设有以下情况:搜索树每个结点的分支很多,并且问题的答案在一个较浅的结点上。如果深搜在一开始选错了分支,就很可能在不包含答案的深层子节树上浪费许多时间。
如下图所示,左半部分是问题的状态空间,菱形表示答案,那么深度优先搜索产生的搜索树如下图所示,算法在矩阵圈出的深层子树上浪费了许多时间。

此时,我们可以从小到大限制搜索的深度,如果在当前深度下搜索不到答案,就把深度限制增加,重新进行一次搜索,这就是迭代加深的思想。

虽然该过程在深度限制为 d 的时候,会重复搜索 1~d-1 层的结点,但是当搜索数节点分支数目较多的时,随着层数的深入,每层节点会呈指数级增长,这点重复搜索和深层子树的规模相比,就是小巫见大巫了。
总而言之,当搜索树规模随着层次的深入增长很快,并且我们能够保证答案在一个较浅层次的节点的时候,就可以采用迭代加深的深度优先搜索算法来解决问题。
输入样例:
5 7 12 15 77 0输出样例:
1 2 4 5 1 2 4 6 7 1 2 4 8 12 1 2 4 5 10 15 1 2 4 8 9 17 34 68 77
剪枝1:优先枚举较大的数
剪枝2:排除等效冗余
- #include
- #include
- #include
-
- using namespace std;
-
- const int N = 110;
-
- int n;
- int path[N];
-
- bool dfs(int u, int depth)
- {
- if(u > depth) return false;
- if(path[u - 1] == n) return true;
-
- bool st[N] = {0};
- for(int i = u - 1; i >= 0; i -- )
- for(int j = i; j >= 0; j --)
- {
- int s = path[i] + path[j];
- if(s > n || s <= path[u - 1] || st[u]) continue;
-
- st[s] = true;
- path[u] = s;
- if(dfs(u + 1, depth)) return true;
- }
- return false;
- }
-
- int main()
- {
- path[0] = 1;
- while(cin >> n, n)
- {
- int depth = 1;
- while(!dfs(1, depth)) depth ++ ;
- for(int i = 0; i < depth ; i ++ ) cout << path[i] << ' ';
- cout << endl;
- }
- return 0;
- }
输入样例:
20 5 7 5 4 18 1输出样例:
19
- #include
- #include
- #include
-
- using namespace std;
-
- typedef long long LL;
-
- const int N = 1 << 24;
-
- int n, m, k;
- int g[50], weights[N];
- int cnt = 0;
- int ans;
-
-
- void dfs(int u, int s)
- {
- if (u == k)
- {
- weights[cnt ++ ] = s;
- return;
- }
-
- if ((LL)s + g[u] <= m) dfs(u + 1, s + g[u]);
- dfs(u + 1, s);
- }
-
-
- void dfs2(int u, int s)
- {
- if (u == n)
- {
- int l = 0, r = cnt - 1;
- while (l < r)
- {
- int mid = l + r + 1 >> 1;
- if (weights[mid] + (LL)s <= m) l = mid;
- else r = mid - 1;
- }
- if (weights[l] + (LL)s <= m) ans = max(ans, weights[l] + s);
-
- return;
- }
-
- if ((LL)s + g[u] <= m) dfs2(u + 1, s + g[u]);
- dfs2(u + 1, s);
- }
-
-
- int main()
- {
- cin >> m >> n;
- for (int i = 0; i < n; i ++ ) cin >> g[i];
-
- sort(g, g + n);
- reverse(g, g + n);
-
- k = n / 2; // 防止 n = 1时,出现死循环
- dfs(0, 0);
-
- sort(weights, weights + cnt);
- int t = 1;
- for (int i = 1; i < cnt; i ++ )
- if (weights[i] != weights[i - 1])
- weights[t ++ ] = weights[i];
- cnt = t;
-
- dfs2(k, 0);
-
- cout << ans << endl;
-
- return 0;
- }
-