埃及分数,迭代加深搜索

来源:互联网 发布:淘宝 海外买手现场 编辑:程序博客网 时间:2024/05/18 00:35

在古埃及,人们使用单位分数的和(形如1/a的, a是自然数)表示一切有理数。 

如:2/3=1/2+1/6,但不允许2/3=1/3+1/3,因为加数中有相同的。 

对于一个分数a/b,表示方法有很多种,但是哪种最好呢? 

首先,加数少的比加数多的好,其次,加数个数相同的,最小的分数越大越好。

如: 19/45=1/3 + 1/12 + 1/180  19/45=1/3 + 1/15 + 1/45  19/45=1/3 + 1/18 + 1/30,  19/45=1/4 + 1/6 + 1/180  19/45=1/5 + 1/6 + 1/18. 最好的是最后一种,因为1/18比1/180,1/45,1/30,1/180都大。  给出a,b(0〈a〈b〈1000),编程计算最好的表达方式。

 

利用枚举深度上限d,每次只考虑深度不超过d的结点。

利用深度上限来剪枝,当当前的分数和为sum,此时拓展的分数为1/val,那么我们至少还需要(inval - sum)/(1/val)个分数才能使和为给定值,

那么超过了此时限定深度的结点则不必考虑,depth - d为此时剩余需要考虑的层数,inval - sum为剩余所需和的大小,(inval - sum) / (depth - d)则为每个剩余分数的值(此时将这些值视为相等),因为我们是使分母逐渐扩大的,则相应的值应该越来越小,所以(inval - sum) / (depth - d)的倒数就是此时最大可以被接受的分母,不然就会超过限定深度。

 

#include"iostream"using namespace std;const double error = 1e-7;int depth = 1;double inval;_inline double mabs(double x){return x > 0 ? x :(-x);}bool dfs(int d,int val,double sum){if(d == depth){if(mabs(sum - inval) < error)return true;return false;}int max = (int)((depth - d)/(inval - sum));            //构造剪枝条件(此处max为最大可以取的val值,即分母)for( ; val <= max ; val ++){if(dfs(d + 1,val + 1,sum + (1.0 / val))){printf(" + 1/ %d ",val);return true;}}return false;}int main(void){int a,b;scanf("%d %d",&a,&b);inval = (double)a/b;while(dfs(0,(int)(1.0/inval) + 1,0.0) == 0){depth ++;}return 0;}            


 

原创粉丝点击