深度优先搜索的优化与技巧
迭代加深
DFS在一些问题模型中可能无限扩展,如8数码问题,无限扩展会有些问题,增
加深度限制:假设目标状态所处深度不超过某阈值。人为设定,当搜索深度到达阈
值时直接剪枝,不再往下搜索。
Iterative Deepening Depth - First Search
适用:求最优/深度最低/步数最少解,当问题深度和广度都大的时候
方式:不断放宽迭代深度限制第一次找到的目标状态即为最优解。
迭代加深是深搜和广搜的结合,普通深搜求最优解必须遍历所有状态打擂台得到,
迭代加深后,第一次遇见目标状态即可得到最优解。
深度优先搜索优化-迭代加深(IDDFS)
for(int dep=1;;dep++)
{//限定每次搜索的深度
if(dfs(1,dep)) break;//找到答案就退出
}
例题1443:【例题4】Addition Chains
n范围较小,初略推出最多十项左右就能得到答案,即答案在搜索树的浅层,可
以使用迭代加深的方法,限制每一次的搜索深度。
例题代码
#include<iostream>
#include<cstring>
using namespace std;
int n,a[105],vis[10005];
bool flag = false;
int dfs(int x,int depth)
{
if(x>depth)
return 0;
if(flag==true)
return 1;
bool vis[5500] = {0};
for (int i = x - 1; i >= 1;i--)
{
for (int j = i; j >= 1;j--)
{
int s = a[i] + a[j];
if(vis[s]==1)
continue;
if(s>n||s<a[x-1])
continue;
a[x] = s;
vis[s] = 1;
if(s==n)
{
for (int i = 1; i <= x;i++)
cout << a[i] << " ";
cout << endl;
flag = 1;
return 1;
}
dfs(x + 1, depth);
}
}
return 0;
}
int main()
{
while(cin>>n&&n)
{
memset(a, 0, sizeof(a));
a[1] = 1;
flag = false;
if(n==1)
{
cout << 1 << endl;
continue;
}
for (int dep = 2;;dep++)
{
if(dfs(2,dep))
break;
}
}
}
折半搜索
例题P4799 [CEOI2015 Day2]世界冰球锦标赛
例题代码
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
ll pri[55], p1[5000005], ans, n, m, tot;
void dfs1(int x,ll cost)
{
if (x==(n>>1)+1)
{
p1[++tot]=cost;
return;
}
if(cost+pri[x]<=m)
dfs1(x+1, cost+pri[x]);
dfs1(x+1, cost);
}
void dfs2(int x,ll cost)
{
if(x>n)
{
int l=1, r=tot, add=0;
while (l<=r)
{
int mid=((r-l)>>1)+l;
if (p1[mid]+cost<=m)
{
l=mid+1;
add=mid;
}
else
r=mid-1;
}
ans+=add;
return;
}
if(cost+pri[x]<=m)
dfs2(x+1, cost+pri[x]);
dfs2(x+1, cost);
}
int main()
{
cin>>n>>m;
for (int i=1;i<=n;i++)
cin>>pri[i];
dfs1(1,0);
sort(p1+1, p1+1+tot);
dfs2(n/2+1,0);
cout<<ans;
}
IDA*
A*与迭代加深的结合使用,通过估价函数计算出递归的层数,若大于当前设定的最大层数,直接剪枝