题意:求a/b的最好的埃及分数表达方式(0<a<b<1000)。加数少的比多的好,加数想等的最小分数值最大好。
迭代加深搜索的经典例题。
本想从分数值最小者开始扩展,这样第一个找到的即为答案,然而没办法剪枝。
原先递归的边界是d == 0
,结果随便弄俩数就卡住了,于是修改为d == 1
。
要使用long long
。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAX_D = 100;
typedef long long ll;
bool flag;
int deno[MAX_D], best[MAX_D];
ll gcd(ll a, ll b)
{
return b ? gcd(b, a%b) : a;
}
bool dfs(int a, int b, int c, int d)
{
if (d == 1) {
if (a != 1 || b < c)
return false;
deno[0] = b;
if (!flag || deno[0] < best[0])
memcpy(best, deno, sizeof(deno));
return flag = true;
}
if ((ll)a*c > (ll)b*d)
return false;
bool ok = false;
for (int i = max(c, (b+a-1)/a); a*i <= b*d; ++i) {
ll x = (ll)a*i-b, y = (ll)b*i, z = gcd(x, y);
deno[d-1] = i;
ok = dfs(x/z, y/z, i+1, d-1) || ok;
}
return ok;
}
int main()
{
int a, b, d;
scanf("%d %d", &a, &b);
for (d = 1; !dfs(a, b, 2, d); ++d)
;
for (int i = d-1; i >= 0; --i)
printf("%d%c", best[i], " \n"[!i]);
return 0;
}