codevs1288 埃及分数

题目描述:

在古埃及,人们使用单位分数的和(形如1/a的, a是自然数)表示一切有理数。 如:2/3=1/2+1/6,但不允许2/3=1/3+1/3,因为加数中有相同的。

对于一个分数a/b,表示方法有很多种,但是哪种最好呢?

首先,加数少的比加数多的好,其次,加数个数相同的,最小的分数越大越 好。

如: 19/45=1/3 + 1/12 + 1/180 19/45=1/3 + 1/15 + 1/45 19/45=1/3 + 1/18 + 1/30, 19/45=1/4 + 1/6 + 1/180 19/45=1/5 + 1/6 + 1/18. 最好的是最后一种,因为1/18比1/180,1/45,1/30,1/180都大。

给出a,b(0<a<b<1000),编程计算最好的表达方式。

题解:
搜索。迭代加深搜索,也称IDDFS。

搞一搞边界剪一剪枝。

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
ll a,b;
ll ans[1000500],tmp[1000500];
ll gcd(ll x,ll y)
{
    if(!y)return x;
    return gcd(y,x%y);
}
ll aa,bb,Gcd,i,lim;
void dfs(ll u,ll dep,ll la,ll lb)
{
    if(dep==lim)
    {
        if(la==1&&u<=lb)
        {
            tmp[lim]=lb;
            if(lb<=ans[lim]||!ans[lim])
            {
                for(i=1;i<=lim;i++)
                    ans[i]=tmp[i];
            }
        }
        return ;
    }
    if(u*la>lb*(lim-dep+1))return ;
    if(ans[lim]&&u>ans[lim])return ;
    dfs(u+1,dep,la,lb);
    tmp[dep]=u;
    aa = la*u-lb,bb = lb*u;
    if(aa<0)return ;
    Gcd = gcd(aa,bb);
    aa/=Gcd,bb/=Gcd;
    dfs(u+1,dep+1,aa,bb);
}
int main()
{
    scanf("%lld%lld",&a,&b);
    Gcd = gcd(a,b);
    a/=Gcd,b/=Gcd;
    for(lim=1;;lim++)
    {
        dfs(b/a,1,a,b);
        if(ans[1])break;
    }
    for(i=1;ans[i];i++)
        printf("%lld ",ans[i]);
    printf("\n");
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/LiGuanlin1124/p/10003315.html