迭代加深搜索,實質上是限定下界的深度優先搜索。即首先允許深度優先搜索K層,若沒有發現可行解,再將K+1後重復以上步驟搜索,直到搜索到可行解。
迭代搜索深度是一個比較炫酷的搜索方式,不過有點拿時間換空間的感覺。
首先迭代深度比較搓的寫法是,首先設置一個閥值MaxH,初始爲最小值。當在搜索深度Depth <= MaxH時找到解則此時爲最優解,否則MaxH++,繼續深搜。
另外一種比較吊的寫法是二分搜索深度,若搜到則減小閥值,否則增大閥值。
總之,迭代深度搜索就是通過改變深搜的深度來尋找最優解,這樣做的好處是省掉了BFS中狀態標記所有的空間花銷。
在迭代加深搜索的算法中,連續的深度優先搜索被引入,每一個深度約束逐次加1,直到搜索到目標爲止。這樣可以看出重複搜索了好多。但是它的好處在於:
1.空間開銷小 每個深度下實際上是一個深度優先搜索,不過深度有限制,而DFS的空間消耗小是衆所周知的。
2.利於深度剪枝
3.時間效率不低 雖然重複搜索,但是大家不難理解,前一次搜索跟後一次相不是微不足到的。
我們可以看出,迭代加深搜索算法就是仿廣度優先搜索的深度優先搜索。既能滿足深度優先搜索的線性存儲要求,又能保證發現一個最小深度的目標結點。
從實際應用來看,迭代加深搜索的效果比較好,並不比廣度優先搜索慢很多,但是空間複雜度卻與深度優先搜索相同,比廣度優先搜索小很多。
使用搜索算法的時候,選擇正確的搜索方式很重要。當有一類問題需要做廣度優先搜索,但卻沒有足夠的空間,而時間卻很充裕,碰到這類問題,我們可以選擇迭代加深搜索算法。
大家可以百度一下埃及分數的題面,沒有確認到哪個oj有這個題目,也不知道哪裏流傳出來的……
#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;
}