迭代加深搜索,实质上是限定下界的深度优先搜索。即首先允许深度优先搜索K层,若没有发现可行解,再将K+1后重复以上步骤搜索,直到搜索到可行解。
在迭代加深搜索的算法中,连续的深度优先搜索被引入,每一个深度约束逐次加1,直到搜索到目标为止。这样可以看出重复搜索了好多。但是它的好处在于:
1.空间开销小 因为每个深度下实际上是一个深度优先搜索,不过深度有限制,而DFS的空间消耗小是众所周知的。
2.利于深度剪枝
3.时间效率不低 虽然重复搜索,但是大家不难理解,前一次搜索跟后一次相不是微不足到的。
我们可以看出,迭代加深搜索算法就是仿广度优先搜索的深度优先搜索。既能满足深度优先搜索的线性存储要求,又能保证发现一个最小深度的目标结点。
从实际应用来看,迭代加深搜索的效果比较好,并不比广度优先搜索慢很多,但是空间复杂度却与深度优先搜索相同,比广度优先搜索小很多。
使用搜索算法的时候,选择正确的搜索方式很重要。当有一类问题需要做广度优先搜索,但却没有足够的空间,而时间却很充裕,碰到这类问题,我们可以选择迭代加深搜索算法。
题目:http://acm.nefu.edu.cn/JudgeOnline/problemshow.php?problem_id=358
题意:给你个真分数,你需要将其化简为最少的若干特殊真分数之和,你要输出这个序列(序列按递增序)。如果有不同的方案,则分数个数相同的情况下使最大的分母最小。若还相同,则使次大的分母最大……以此类推。如:2/3=1/2+1/6,但不允许2/3=1/3+1/3,因为加数中有相同的。对于一个分数a/b,表示方法有很多种,但是哪种最好呢? 首先,加数少的比加数多的好,其次,加数个数相同的,最小的分数越大越好。
#include <iostream> #include <string.h> #include <stdio.h> using namespace std; typedef long long LL; const int INF = ~0U>>1; const int N = 10; int dep,flag; int ans[N],d[N]; int gcd(int a,int b) { return b ? gcd(b,a%b):a; } void dfs(int a,int b,int k) { if(k == dep + 1) return; if(b % a == 0 && b / a > d[k-1]) { d[k] = b / a; if(!flag || d[k] < ans[k]) memcpy(ans,d,sizeof(d)); flag = 1; return; } int s = b / a; if(s <= d[k-1]) s = d[k-1] + 1; int t = (dep - k + 1) * b / a; if(t > INF / b) t = INF / b; if(flag && t >= ans[dep]) t = ans[dep] - 1; for(int i=s;i<=t;i++) { d[k] = i; int m = gcd(i*a - b,b*i); dfs((i*a-b)/m,b*i/m,k+1); } } void Work(int a,int b) { d[0] = 1; flag = 0; for(dep=1;dep <= N;dep++) { dfs(a,b,1); if(flag) { printf("1/%d",ans[1]); for(int i=2;i<=dep;i++) printf("+1/%d",ans[i]); cout<<endl; break; } } } int main() { int a,b; while(cin>>a>>b) { cout<<a<<"/"<<b<<"="; Work(a,b); } return 0; }