UVA12558 Egyptian Fractions (HARD version) (埃及分数)

UVA12558 Egyptian Fractions (HARD version)

题解

迭代加深搜索,适用于无上界的搜索。每次在一个限定范围中搜索,如果无解再进一步扩大查找范围。

本题中没有分数个数和分母的上限,只用爆搜绝对TLE。故只能用迭代加深搜索。

#include<cstdio>
#include<cstring>
#include<set>
using namespace std;
typedef long long ll;
int num,T,t,k;
ll h[100001],ans[100001],a,b,q;
set <ll> del; //存储不能用的数
bool ok;
inline ll gcd(ll A,ll B) {return B ? gcd(B,A%B):A;}
inline bool better(){ //判断最优解
    for(int i=num;i>=0;--i)
        if(h[i]!=ans[i])
            return ans[i]==-1||h[i]<ans[i];
    return 0;
}
inline void dfs(ll p1,ll p2,int last,int cnt){//p1/p2:分子/分母 last:这次从哪个分母开始搜 cnt:已经添加了几个子分数
    if(cnt==num){
        if(p2%p1||del.count(p2/p1)) return ; //分子不为1或者这个数被禁止出现
        h[cnt]=p2; ok=1;
        if(better()) memcpy(ans,h,sizeof(ll)*(cnt+1)); //更新最优解
        return ;
    }
    for(ll i= last>p2/p1+1 ? last:p2/p1+1;;++i) // p2/p1+1:符合条件的最小分母,用于剪枝
    {
        if(p1*i>=p2*(num-cnt+1)) break; //发现最后减不完了,跳出
        if(del.count(i)) continue;
        ll q1=p1*i-p2,q2=p2*i,G=gcd(q1,q2); //通分
        h[cnt]=i;
        dfs(q1/G,q2/G,i+1,cnt+1);
    }
}
int main(){
    scanf("%d",&T);
    for(t=1;t<=T;++t){
        del.clear(); ok=0;
        scanf("%lld%lld%d",&a,&b,&k);
        for(int i=1;i<=k;++i) scanf("%lld",&q),del.insert(q);
        for(num=1;!ok;++num){
            memset(ans,-1,sizeof(ans));
            dfs(a,b,b/a+1,0); //b/a+1同上p2/p1+1
        }--num; //注意要减掉多出的一次++num操作
        printf("Case %d: %lld/%lld=",t,a,b);
        for(int i=0;i<num;++i) printf("1/%lld+",ans[i]);
        printf("1/%lld\n",ans[num]);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/kafuuchino/p/9580419.html

时间: 2024-11-08 04:36:39

UVA12558 Egyptian Fractions (HARD version) (埃及分数)的相关文章

UVA-12558 Egyptian Fractions (HARD version) (IDA* 或 迭代加深搜索)

题目大意:经典的埃及分数问题. 代码如下: # include<iostream> # include<cstdio> # include<cstring> # include<algorithm> using namespace std; # define LL long long int num[5],a,b,k; LL ans[10000],v[10000]; LL gcd(LL a,LL b) { return (b==0)?a:gcd(b,a%b)

UVA 12558 Egyptian Fractions (HARD version)

题意: 经典的埃及分数问题,即给出一个真分数,求出用个数最少的单位分数来表示这个分数.如果有多种方案,要让每个分数尽量的大,即分母尽量的小.会有K个禁止使用的单位分数. 分析:    IDA*算法.当按照分母递增的顺序排列时, 如果当前考虑的分数为1/e,剩下的maxd - d+1层都是1/e,但仍然到不了目标的a/b的时候,就剪枝. 代码: #include <iostream>#include <cstdio>#include <cstring>#include &

【习题 7-7 UVA-12558】Egyptian Fractions (HARD version)

[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 迭代加深搜索. 枚举最大量maxdep 在dfs里面传剩余的要凑的分子.分母 以及上一次枚举的值是多少. 然后找到最小的k,满足1/k<=分子/分母 然后从max(k,last+1)开始枚举. ->剪枝就是剩余的全都用这个最大的分数.如果都不行就肯定不行了. 二分找这个k. 不能用的数字就直接跳过就行. [代码] /* 1.Shoud it use long long ? 2.Have you ever test severa

12558 - Egyptian Fractions (HARD version)(IDA*算法)

IDA*算法,迭代加深搜索和A*算法的结合 . 迭代加深搜索适用于那些没有明显深度上限的题目,将深度从小到大枚举,直到找到最优解 ,减小了深搜的盲目性 . A*算法需要一个乐观估价函数,在这个函数里寻找一个代价最小的点去搜索,所以时间复杂度都浪费在这个上面了 . 代码如下: #include<bits/stdc++.h> using namespace std; typedef long long ll; int T,kase=0; ll v[10000+10],ans[10000+10],a

12558 - Egyptian Fractions (HARD version)

#include<cstdio> #include<cstring> #include<algorithm> #include<set> using namespace std; typedef long long LL; const int maxn=10010; int maxd,t,tt; set<LL> sk; LL ans[maxn],v[maxn]; LL gcd(LL a,LL b){ return b?gcd(b, a%b):a;

UVA_埃及分数(Hard Version) UVA 12588

Problem EEg[y]ptian Fractions (HARD version)Given a fraction a/b, write it as a sum of different Egyptian fraction. Forexample, 2/3=1/2+1/6.There is one restriction though: there are k restricted integers that should notbe used as a denominator. For

UVA12558-Efyptian Fractions(HARD version)(迭代加深搜索)

Problem UVA12558-Efyptian Fractions(HARD version) Accept:187  Submit:3183 Time Limit: 3000 mSec  Problem Description Given a fraction a/b, write it as a sum of different Egyptian fraction. For example, 2/3 = 1/2 + 1/6. Thereisonerestrictionthough: th

1288 埃及分数

1288 埃及分数 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题解 查看运行结果 题目描述 Description 在古埃及,人们使用单位分数的和(形如1/a的, a是自然数)表示一切有理数. 如:2/3=1/2+1/6,但不允许2/3=1/3+1/3,因为加数中有相同的. 对于一个分数a/b,表示方法有很多种,但是哪种最好呢? 首先,加数少的比加数多的好,其次,加数个数相同的,最小的分数越大越 好. 如: 19/45=1/3 + 1/12 + 1/

【迭代加深搜索】埃及分数问题

谢谢阿苏~http://blog.csdn.net/urecvbnkuhbh_54245df/article/details/5856756 [迭代加深搜索(ID,iterative deepening)]:从小到大枚举上限maxd,每次执行只考虑深度不超过maxd的结点. ------对于可以用回溯法求解但解答树的深度没有明显上限的题目,可以考虑ID算法: ------优点:它主要是在递归搜索函数的开头判断当前搜索的深度是否大于预定义的最大搜索深度,如果大于,就退出这一层的搜索,如果不大于,就