Loading

埃及分数问题 迭代加深搜索/IDA*

输入整数a,b (0<a<b<500) ,输出最佳表达式 使得加数个数尽量小,如果加数个数相同,则最小的分数越大越好 ,输出表达式

考虑从小到大枚举深度上限maxd,每次执行只考虑深度不超过maxd的结点。当前的结点n的深度为g(n),乐观估价函数为h(n),则当

g(n)+h(n)>maxd时应该剪枝,这就是IDA*算法。

#include<iostream>
#include<string>
#include<cmath>
#include<cstring>
#include<vector>
#include<map>
#include<set>
#include<algorithm>
#include<queue>
#include<stack>
#include<sstream>
#include<cstdio>
#define INF 0x3f3f3f3f
//const int maxn = 1e6 + 5;
const double PI = acos(-1.0);
typedef long long ll;
using namespace std;

int a, b, maxd;

ll gcd(ll a, ll b) {
    return b == 0 ? a : gcd(b, a % b);
}

inline int get_first(ll a, ll b) {
    return b / a + 1;
}

const int maxn = 100 + 5;

ll v[maxn], ans[maxn];

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 (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 (bb * (maxd + 1 - d) <= i * aa)  break;
        v[d] = i;
        ll b2 = bb * i;
        ll a2 = aa * i - bb;
        ll g = gcd(a2, b2);
        if (dfs(d + 1, i + 1, a2 / g, b2 / g)) ok = true;
    }
    return ok;
}

int main() {
    int kase = 0;
    while (scanf("%d%d", &a, &b) != EOF) {
        int ok = 0;
        for (maxd = 1; maxd <= 100; maxd++) {
            memset(ans, -1, sizeof ans);
            if (dfs(0, get_first(a, b), a, b)) {
                ok = 1;
                break;
            }
        }
        printf("Case %d: ", ++kase);
        if (ok) {
            printf("%d/%d=",a,b);
            for (int i = 0; i < maxd; i++) printf("1/%lld+", ans[i]);
            printf("1/%lld\n", ans[maxd]);
        }
        else printf("No solution\n");
    }
    return 0;
}

 

posted @ 2020-02-25 11:15  MQFLLY  阅读(235)  评论(0编辑  收藏  举报