做法:
从根节点开始 d f s dfs dfs,用一个变量 d e p dep dep限制 d f s dfs dfs的深度,一旦达到 d e p dep dep层,那么就看是否找到目标;如果在 d e p dep dep层没有搜索到目标,那么就将深度的限制 d e p + 1 dep+1 dep+1,继续从根节点重新开始 d f s dfs dfs,如此反复直到找到目标,或者证明目标不存在;
适用于的题目
- 能够从题目中推断出答案的层次较浅;
- 整个搜索树非常的深而且随着深度的增加,结点增加非常快速;
优势
- 相比于dfs,防止一条路走到底,避免超时
- 相比于bfs,防止在队列中存储的状态过多,避免超空间;
劣势:
每一次都需要从根节点重新开始搜索,会导致重复;
代码基本框架
bool dfs(int cur)
{
if (cur==dep)
{
return true/false;
}
for (cur的邻居)
{
if(dfs(next)==true)
{
return true;
}
}
return false;
}
int main()
{
dep=1;
while (dfs(root)==false)
{
dep++;
}
}
例题:
Sample 1:POJ2248 Addition Chains/UVA529 Addition Chains
思路:
- 搜索的逻辑,从第1个数开始搜索,对于待搜索的第i项,只可能由1到-1的两个数值加起来得到。
注意,需要剪枝,分别是排除重复以及优化搜索顺序
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<cmath>
using namespace std;
const int maxn=105;
const int INF=0x3f3f3f3f;
int n,dep;
int ans[maxn];
inline int read()
{
int s=0,f=1;
char c=getchar();
while (c<'0'||c>'9')
{
if (c=='-')
{
f=-1;
}
c=getchar();
}
while (c>='0'&&c<='9')
{
s=(s<<1)+(s<<3)+c-'0';
c=getchar();
}
return s*f;
}
inline void write(int x)
{
if (x<0)
{
x=~(x-1);
putchar('-');
}
if (x>9)
{
write(x/10);
}
putchar(x%10+'0');
}
inline bool dfs(int cur) //目前已经在位置1到cur找到结果
{
if (cur==dep) //搜索到与 当前迭代的深度的限制相等
{
return ans[cur]==n;
}
bool vis[maxn]={false}; //排除重复(剪枝)
for (int i=cur;i>=1;i--) //优化搜索顺序(剪枝)
{
for (int j=i;j>=1;j--) //i,j可以相等
{
int num=ans[i]+ans[j]; //和
if (num<=n&&num>ans[cur]&&vis[num]==false)
{
ans[cur+1]=num;
if (dfs(cur+1)==true)
{
return true;
}
else
{
vis[num]=true;
}
}
}
}
return false;
}
int main()
{
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
ans[1]=1;
while (17)
{
n=read();
if (n==0)
{
break;
}
dep=1;
while (dfs(1)==false)
{
dep++; //迭代深度
}
for (int i=1;i<=dep;i++)
{
write(ans[i]);
printf(" ");
}
puts("");
}
return 0;
}
Sample 2:POJ3134 Power Calculus/UVA1374 快速幂计算 Power Calculus
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<cmath>
using namespace std;
const int maxn=100005;
const int INF=0x3f3f3f3f;
int n,dep;
int ans[maxn];
inline int read()
{
int s=0,f=1;
char c=getchar();
while (c<'0'||c>'9')
{
if (c=='-')
{
f=-1;
}
c=getchar();
}
while (c>='0'&&c<='9')
{
s=(s<<1)+(s<<3)+c-'0';
c=getchar();
}
return s*f;
}
inline void write(int x)
{
if (x<0)
{
x=~(x-1);
putchar('-');
}
if (x>9)
{
write(x/10);
}
putchar(x%10+'0');
}
inline bool dfs(int cur)
{
if (cur==dep)
{
return ans[cur]==n;
}
int maxi=-INF;
for (int i=1;i<=cur;i++)
{
maxi=max(maxi,ans[i]);
}
if ((maxi<<(dep-cur))<n)
{
return false;
}
for (int i=cur;i>=0;i--)
{
ans[cur+1]=ans[cur]+ans[i];
if (dfs(cur+1)==true)
{
return true;
}
ans[cur+1]=ans[cur]-ans[i];
if (dfs(cur+1)==true)
{
return true;
}
}
return false;
}
int main()
{
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
while (1)
{
n=read();
if (n==0)
{
break;
}
dep=0;
ans[0]=1;
while (dfs(0)==false)
{
dep++;
}
write(dep);
puts("");
}
return 0;
}
/*
1
31
70
91
473
512
811
953
0
*/