迭代加深搜索:这是一种类似广搜的深搜,但是它不需要广搜如此大的空间,它的空间与深搜的空间一样,那么这时问题就来了,迭代深搜怎么实现呢?
我们需要用到一个dep变量(名字可以自己取),用于枚举迭代深搜的深度,
那么从这个图中不难看出,dep枚举的是搜索的深度,一般性一开始都定为1(你也可以随便定一个数),每次累加一般累加1。
迭代加深的应用主要在于这么一道家喻户晓的题目:埃及分数
这道题首先看上去没有什么思路,如果广搜空间必然承受不了,单一的深搜时间又太慢,不难想到要用一些带技巧的搜索,可是如果只是简单的剪枝,能剪下复杂度吗?答案是否定的,唯一的办法就是A*或迭代深搜,这里我们主要讲迭代深搜!
#include<stdio.h>
#include<stdlib.h>
#include<cstring>
#include<iostream>
using namespace std;
#define up(a,b,c) for(a=b;a<=c;a++)
#define ll long long
const int INF= ~0U>>1;
ll dep=1,ans[11],d[11],flag;
ll gcd(ll a,ll b){
return b==0?a:gcd(b,a%b);
}
void dfs(ll a,ll b,int sum){
ll i;
if(sum>dep)return;
if(a==1 && b>d[sum-1]){
d[sum]=b;
if(!flag || d[sum]<ans[sum]){
memcpy(ans,d,sizeof(d));
}
flag=1;
return;
}
ll l=b/a;
if(l<=d[sum-1])l=d[sum-1]+1;
ll r=(dep-sum+1)*b/a;
if(r>INF)r=INF-1;
if(flag && r>=ans[dep])r=ans[dep]-1;
up(i,l,r){
d[sum]=i;
ll gc=gcd(i*a-b,b*i);
dfs((i*a-b)/gc,b*i/gc,sum+1);
}
}
int main(){
int i,j,k,n,m;
long long a,b;
cin>>a>>b;
ll c=gcd(a,b);
a/=c;b/=c;d[0]=1;
if(a==1){
cout<<b<<endl;return 0;
}
while(dep<=10){
dfs(a,b,1);
if(flag){
for(i=1;i<=dep;i++)
printf("%lld ",ans[i]);
puts("");
return 0;
}
dep++;
}
return 0;
}
这是笔者的代码,不难理解其中的一些关键部分,这个里面还有一些重要的剪枝,像如果枚举到了最后一个数,那么它必定是a/b-前面数的埃及分数和!知道了这个条件有如神助,当然,还有别的剪枝方法,如果想了解剪枝请关注以后的文章(与生日蛋糕有关)!