UVA 12558 Egyptian Fractions (HARD version)

来源:互联网 发布:噪声检测软件哪款好 编辑:程序博客网 时间:2024/05/20 07:33

题意:把a/b写成不同的埃及分数之和(1/i),要求项数尽量小,在此前提下最小的分数尽量大,然后第二小的分数尽量大...另外有k个数不能用作分母,加数中不允许有相同的,试计算最佳表达式

解题思路:迭代加深搜索IDA*.经典题目,具体见代码注释

代码:

#include <iostream>#include <algorithm>#include <cstring>#include <string>#include <cmath>#include <cstdio>#include <set>using namespace std;typedef long long ll;set<ll> s;int maxd;ll ans[10010],v[10010];ll gcd(ll a,ll b){    return b?gcd(b,a%b):a;}ll get_first(ll a,ll b)//得到满足1/c<=a/b的最小c{    return b/a+1;}bool better(int d)//判断当前的解是否为最优解{    for(int i=d;i>=0;i--)    {        if(v[i]!=ans[i])return ans[i]==-1||v[i]<ans[i];    }    return false;}bool dfs(int d,ll from,ll a,ll b)//当前深度d,分母不能小于from,分数之和恰好为a/b{    if(d==maxd)    {        if(b%a)return false;//a/b必须是埃及分数        v[d]=b/a;        if(s.count(b/a))return false;//筛掉禁止使用的字符        if(better(d))memcpy(ans,v,sizeof(ll)*(d+1));        return true;    }    bool ok=false;    from=max(from,get_first(a,b));//枚举起点    for(ll i=from;;i++)    {        if(b*(maxd+1-d)<=i*a)break;//剪枝,如果剩下的maxd+1-d个分数全为1/i,加起来仍小于a/b,无解        if(s.count(i))continue;        v[d]=i;        ll b2=b*i;//计算a/b-1/i,设结果为a2/b2        ll a2=a*i-b;        ll g=gcd(a2,b2);//以便约分        if(dfs(d+1,i+1,a2/g,b2/g))ok=true;    }    return ok;}int main(){    int t;    cin>>t;    int cas=0;    while(t--)    {        ll a,b,k,kk;        s.clear();        cin>>a>>b>>k;        while(k--)        {            cin>>kk;            s.insert(kk);        }        for(maxd=0;;maxd++)        {            memset(ans,-1,sizeof(ans));            if(dfs(0,get_first(a,b),a,b))break;        }        cout<<"Case "<<++cas<<": "<<a<<"/"<<b<<"=";        for(int i=0;i<=maxd;i++)        {            if(i)cout<<"+";            cout<<"1/"<<ans[i];        }        cout<<endl;    }    return 0;}


阅读全文
0 0
原创粉丝点击