习题7-7 Egyptian Fractions (HARD version) 埃及分数 (IDA*)

来源:互联网 发布:j2直播软件 编辑:程序博客网 时间:2024/05/20 08:44

大体题意:

在普通的埃及分数上加了  几个限制, 多给了你K个数,让你求出最后的埃及分数结果中分母不能是K个数的某个数的结果。

思路:

先记录一下 埃及分数算法:

利用了迭代加深的搜索方式

最后的分母结果记录在ans数组中,最后只需要输出ans 数组即可!

首先将ans数组初始化为-1,表示没赋过值,这样在更新答案时,可以判断ans[i] == 1或者  v[i] < ans[i]  这样可以更新ans数组!

在dfs 函数中,有一个深度d  到达maxd时 进行判断返回,还有一个int from 参数,表示枚举的分母从哪里开始,然后就是目标分子和分母了!

然后d 到达maxd时,判断目标分数是不是埃及分数 和此时是不是更优解。  如果不是埃及分数直接return false了,最后return true;

如果没到达maxd,则先更新一下枚举分母的起源,然后就是剪枝,都合法时算出下一个分数,在进行dfs即可!



该题目多的限制 要在两个地方进行判断,一个是dfs 没到达maxd时在枚举分母时,发现i 时禁止的 直接continue;

另一个地方时 到达maxd时要判断更新的ans 是不是禁止的!、


具体详见代码和书籍!

#include<cstdio>#include<cstring>#include<algorithm>#define fin freopen("cin.txt","r",stdin);#define fout freopen("out.txt","w",stdout);using namespace std;typedef long long ll;const int maxn = 10000 + 10;int maxd,k;int Not[maxn];ll v[maxn],ans[maxn];int get_first(int a,int b){    return b/a+1;}ll gcd(ll a,ll b){    return !b?a:gcd(b,a%b);}bool forbid(int n){    for (int i = 0; i < k; ++i)if (Not[i] == n)return true;    return false;}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,int from, ll aa, ll bb){    if (d == maxd){        if (bb % aa)return false;        v[d] = bb/aa;        if (forbid(bb/aa))return false;        if (better(d))memcpy(ans,v,sizeof(ll) * (d+1));        return true;    }    bool ok = false;    from = max(from,get_first(aa,bb));    for (int i = from;;++i){        if (forbid(i))continue;        if (bb * (maxd-d+1) <= i * aa)break;        v[d] = i;        ll b2 = i*bb;        ll a2 = i*aa-bb;        ll g = gcd(a2,b2);        if (dfs(d+1,i+1,a2/g,b2/g))ok=1;    }    return ok;}int main(){//    fin;fout;    int T,cnt = 0;    scanf("%d",&T);    while(T--){        int a,b;        scanf("%d%d%d",&a,&b,&k);        memset(ans,-1,sizeof ans);        for (int i = 0; i < k; ++i)scanf("%d",&Not[i]);        int ok = 0;        for (maxd = 1;;++maxd){            if (dfs(0,get_first(a,b),a,b)){                ok = 1;                break;            }        }        printf("Case %d: %d/%d=",++cnt,a,b);        for (int i = 0; i <= maxd; ++i){            if (i)printf("+");            printf("1/%lld",ans[i]);        }        printf("\n");    }    return 0;}


0 0
原创粉丝点击