#10022. 「一本通 1.3 练习 1」埃及分数(迭代加深搜索)

Aimee

很显然我们并不知道到底会搜索出多少层

但是最优解一定不会太大

那么迭代加深搜索会是一个好的选择

迭代加深要限制层数,这很显然

那么就此来说,当就剩下一个分数可以选的时候

我们要判断这个分数是不是单位分数,如果他是,再判断一下是不是最优解

这样就解决了dfs中的一半(体积意义上)的问题

if(de==1){
        if(x==1&&y>tem[p]&&(Aimee==0||y<ans[Aimee])){
            Aimee=++p;
            tem[p]=y;
            for(int i=1;i<=Aimee;++i){
                ans[i]=tem[i];
            }
            p--;
            return 1;
        }
        return 0;
    }

为什么每一次都要判断呢,因为求的是当前层数的最优解

dfs的另外一个问题就是怎样向下推导

这里有三个优化

第一个优化

很显然保证字母大小递增

第二个优化

由于优化1可知,我们选的分数越来越小

那也就意味着后面的分数铁定比前面小
所以说当前这个分数的分母为i的话

$frac{1}{i} < frac{x}{y}$

这样取一个最大值就可以知道下界了

第三个优化

取的分数越来越小,那么之后所有的分数之和一定会小于他们都等于当前这个分数

换言之,如果剩下的数都等于当前分数的话,肯定是要大于剩下的分数的数的

那么也就是说,如果$frac{k}{i}>frac{x}{y}$是一定要满足的

不然绝无可能合法

但是这样会损失精度

这很讨厌,那就变成乘法$ky>xi$

剪枝完成

bool dfs(int de,int x,int y,int la){
    if(de==1){
        if(x==1&&y>tem[p]&&(Aimee==0||y<ans[Aimee])){
            Aimee=++p;
            tem[p]=y;
            for(int i=1;i<=Aimee;++i){
                ans[i]=tem[i];
            }
            p--;
            return 1;
        }
        return 0;
    }
    bool key=0;
    for(int i=max(la+1,jdn(x,y));de*y>x*i;++i){
        int yy=y/gcd(y,i)*i;
        int xx=x*(yy/y)-yy/i;
        int gcdd=gcd(xx,yy);
        xx/=gcdd;
        yy/=gcdd; 
        tem[++p]=i;
        if(dfs(de-1,xx,yy,i)) key=1;
        p--;
    } 
    return key;
}

注意一些gcd的小细节以及有可能一开始给了一个埃及分数,那样的话就不能拆分的

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int n,m;
int gcd(int x,int y){
    return y==0?x:gcd(y,x%y); 
}
int p;
int de=1;
int ans[100001];
int Aimee;
int tem[100001];
int jdn(int x,int y){
    for(int i=2;i;++i){
        if(i*x>y)
        return i;
    }
    return 0;
}
void print(){
    for(int i=1;i<=Aimee;++i){
        cout<<ans[i]<<" ";
    }
    return ;
}
bool dfs(int de,int x,int y,int la){
    if(de==1){
        if(x==1&&y>tem[p]&&(Aimee==0||y<ans[Aimee])){
            Aimee=++p;
            tem[p]=y;
            for(int i=1;i<=Aimee;++i){
                ans[i]=tem[i];
            }
            p--;
            return 1;
        }
        return 0;
    }
    bool key=0;
    for(int i=max(la+1,jdn(x,y));de*y>x*i;++i){
        int yy=y/gcd(y,i)*i;
        int xx=x*(yy/y)-yy/i;
        int gcdd=gcd(xx,yy);
        xx/=gcdd;
        yy/=gcdd; 
        tem[++p]=i;
        if(dfs(de-1,xx,yy,i)) key=1;
        p--;
    } 
    return key;
}
int main(){
    scanf("%d%d",&n,&m);
    int gcdd=gcd(n,m);
    n/=gcdd;
    m/=gcdd;
    if(n==1){
        cout<<m;
        return 0;
    }
    while(++de){
        p=0;
        if(dfs(de,n,m,1)){
            print();
            return 0;
        }
    }
    return 0;
}

That's all,thanks。

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇