迭代加深搜索

4 篇文章 0 订阅
3 篇文章 0 订阅

IDDFS 题目 LOJ 10022“埃及分数”

题目链接https://loj.ac/p/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更安全一些

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值