题目大意:给出一个真分数,要求写出他有哪几个埃及数字组成,在数目想等的情况,要求分母最小的那个
解题思路:深度逐层加深,从1开始递增下去,分母从1开始判断,设置一个分母的最大值,以免递归太多次
分子为a,分母为b,分母的最大值为min,该层的埃及数分母最小值为x,
剪枝:1.迭代层数大于等于当前最大次数时或x>=min,也就是分母已经加到最大值了,不必再递归下去了
2.如果 b % a等于零,b=b/a,b>x且b<min,表示后面有分母能表示到该值且不越界,找到了结束的条件了,将b赋值给min,后面的剪枝用得到
3.要求a/b > 1 / x ,也就是当a*x<b时,加上该埃及数就会超过所要求的值,循环寻找符合要求的最小x
4.当x<min时,且a*x<b(max_depth - depth)的数值才会符合,max_depth-depth表示还有几次可以递归,因为剪枝2已经找到了最后的值了,但不能确保那个值是最小的,所以将min改变后,就可以在更小的范围内找到最佳值
#include<cstdio>
#include<cstring>
const int maxn= 100;
int min;
int ans[maxn];
int out[maxn];
// depth表示递归了几次,max_depth表示最多的递归层数,a是分子,b是分母,x是所提供的最小的分母
void dfs(int depth, int max_depth, int a, int b,int x){
if(depth >= max_depth || x >= min)
return ;
if(b % a == 0) {
b = b/a;
if(b < x || b >= min)
return ;
min = b;
ans[depth] = b;
memcpy(out,ans,(depth+1)*sizeof(int));//depth从0开始,所以要加上1
return ;
}
else {
if(depth >= max_depth - 1) return ;
while(a*x<=b && x<min) x++;// a / b > 1 / x
while(x<min) {
if(a*x>=b*(max_depth-depth)) break;//因为后面的值都小于1/x,要确保在接下的max_depth-depth次中的和能为a/b
ans[depth] = x;
depth++;
dfs(depth,max_depth,a*x-b,b*x,x+1);
depth--;
x++;
}
}
return ;
}
int main() {
int m,n;
while(scanf("%d%d",&m,&n) != EOF && m+n) {
min = 1000000;
printf("%d/%d=",m,n);
int i;
for(i = 1;i <= 100; i++) {
dfs(0,i,m,n,1);//i表示要递归的层数
if(min < 1000000)
break;
}
for(int j = 0; j < i - 1 ; j++)
printf("1/%d+",out[j]);
printf("1/%d\n",out[i-1]);
}
return 0;
}