IDDFS 题目 LOJ 10022“埃及分数”
迭代加深,字面意思。适用于搜索树很深而且很宽的题,如果直接使用DFS会陷入递归无法返回;如果直接用BFS,队列可能爆炸。
具体操作模板:
1、先设定搜索深度为1,用DFS搜索到第1层即停止
2、如果没有找到答案,再设定深度为2,用DFS搜索2层即停止
3、继续设定深度为3,4,5巴拉巴拉巴拉,逐步扩大DFS的搜索深度,直到找到答案
每一层的广度上采用了DFS的搜索思想,在具体变成实现上是DFS的搜索思想。
题目分析:
这题可能有多个最优解啊!其他的按模板来就是一个模板题
AC代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int MX=1005;
int maxd=1,mind=1;
LL a,b,den[MX*10],ans[MX*10]; //den临时保存单位分数的分母
//ans保存最终答案代表的分数的分母
//因为都是单位分数,分子为 1,所以只需保存分母即可
LL gcd(LL a,LL b){
return b==0 ? a : gcd(b,a%b);
}
int starT(LL x,LL y){ //确定分母的下界
for (int i=2;;i++){ //即:1/i <= x/y
if (y<=x*i){
return i;
}
}
}
bool can_update(int d){//判断是否更新,如果最小分数的分母比原来的大,那么更新
if (ans[d]==-1) return true;
if (den[d]>ans[d]) return false;
if (den[d]<ans[d]) return true;
for (int i=1;i<=d;i++){//否则从第一个分数开始判断
if (ans[i]==-1) return true;
if (den[i]>ans[i]) return false;
if (den[i]<ans[i]) return true;
}
return false;
}
bool iddfs(int d,int min_den,LL x,LL y){
if (d==maxd){
if (y%x!=0) return false;//不是单位分数
den[d]=y/x; //否则就是一个合法答案,判断是否更新
if (can_update(d)){
for (int i=1;i<=d;i++){
ans[i]=den[i];
}
}
return true;
}
min_den=max(min_den,starT(x,y));
bool ok=false;
for (int i=min_den;;i++){
if (y*(maxd-d+1)<=i*x)
break; //如果之后选的分数大小不超过x/y,则当前加数已经不满足,返回
//即:(maxd-d+1)*(1/i) <= x/y 时,返回
den[d]=i;
LL xx=x*i-y,yy=y*i,g=gcd(xx,yy);
if (iddfs(d+1,i+1,xx/g,yy/g))
ok=true;
}
return ok;
}
int main(){
scanf("%lld%lld",&a,&b);
if (b%a==0){ //如果一开始就是单位分数了,那么直接返回
printf("%lld",b/a);
return 0;
}
mind=starT(a,b);
while (++maxd){
memset(ans,-1,sizeof(ans));
if (iddfs(1,mind,a,b)){
break;
}
}
for (int i=1;i<=maxd;i++){
printf("%lld",ans[i]);
}
return 0;
}
学到了啥捏:
1、scanf,printf比cin,cout速度要快
2、用const代替#define更安全一些