UVa 12558 Egyptian Fractions (HARD version)--迭代加深搜索

来源:互联网 发布:手机恶作剧软件小狗 编辑:程序博客网 时间:2024/05/20 06:30

题目链接:
https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=842&page=show_problem&problem=4003
题目大意:
把一个真分数表示成一系列埃及分数的和,要求项数最少,且最小分数值最大以此类推。并且给出k(5)个数,不能选用
分析:
对于这种没有搜索上限的题最好采用迭代加深搜索,设置一个上限maxd,
上限maxd还可以用来剪枝,当扩展到第i层时,若剩余值为d/c,接下来要考虑的分数为1/e则至少应该满足1/e(maxd+1d)d/c,反之则会被剪枝。

wrong了很多次才发现bug的代码。。
最初的bug:考虑最后一个值即b/a时未考虑b/a是否在给出的K个数内

#include <iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<stack>#define MAXN 100000using namespace std;typedef long long  LL;LL v[MAXN],ans[MAXN];LL maxd;LL a ,b,k,K[10];LL gcd(LL a,LL b){    return b==0?a:gcd(b,a%b);}bool better(LL d){    for(LL i=d ; i>-1; --i)        if(v[i]!=ans[i])return ans[i] == -1||v[i]<ans[i];}bool dfs(LL d,LL from,LL a,LL b){    if(d == maxd)    {        if(b%a)return false;        bool fk = false;        if(b/a<=1000)        {            for(int j = 0 ; j<k ; ++j)                if(K[j] == b/a)            {                fk = true;                break;            }        }        if(fk)return false;        v[d] = b/a;        if(better(d))memcpy(ans,v,sizeof(LL)*(d+1));        return true;    }    from = max(from,b/a+1);    bool ok = false;    for(LL i = from ; ;i++)    {        bool fk  = false;        if(b*(maxd+1-d)<=a*i)break;        if(i<=1000)        {            for(int j = 0 ; j<k ; ++j)                if(K[j] == i)            {                fk = true;                break;            }        }        if(fk)continue;        //i合法,计算剩余分数        v[d] = i;        LL bb = b*i;        LL aa = a*i-b;        LL g = gcd(aa,bb);        if(dfs(d+1,i+1,aa/g,bb/g)){ok = true;}    }    return ok;}int main(){  //freopen("H:\\c++\\file\\stdin.txt","r",stdin);    int T;    scanf("%d",&T);    int kase = 0;    while(T--)    {        scanf("%lld %lld %lld",&a,&b,&k);        for(int i=0 ; i<k ; ++i)scanf("%lld",&K[i]);        for(maxd = 1 ; ;++maxd)        {            memset(ans,-1,sizeof(ans));            if(dfs(0,b/a+1,a,b)){break;}        }        printf("Case %d: ",++kase);        printf("%lld/%lld=",a,b);        for(int i=0 ; i<maxd ; ++i)            printf("1/%lld+",ans[i]);        printf("1/%lld",ans[maxd]);        putchar('\n');    }    return 0;}
0 0
原创粉丝点击