迭代深搜(iddfs)
#include <iostream>
using namespace std;
double n; //所求解
int res[1000]; //存储分母
int depth; //dfs深度即分数个数
int a,b; //a/b
int find;
//求n个数最小公倍数,(除去所有的公约数,就成了最小公倍)
int lcm(int val[],int n)
{
int ret=1;
for (int i = 0;i < n;i ++)
for (int j = i + 1;j <= n;j++)
if (val[j] % val[i] == 0)
val[j] /= val[i];
for(int j=0; j<n; j++)
ret*=val[j];
return ret;
}
//a/b==1/x+1/y+---1/n变形为1==b/ax+b/ay+---b/an,然后化为同分母
//即求化简后分子分母相等,先求所有分子乘以a后的最小公倍数,即为所求分母,再根据分母计算出分子,比较是否相等
int check()
{
int temp[1000];
unsigned int a1=0,b1=0;//a1分子b1分母
memcpy(temp, res,sizeof(res));
for(int i=0; i<depth; i++)
temp[i]*=a;
b1=lcm(temp,depth);
for(int i=0; i<depth; i++)
a1 += b1/res[i]/a*b;
return a1==b1;
}
//cur记录当前所在层,m可以选择的最小的分母,x记录当前所选所有分数得出的中间结果
//由于浮点数精度问题,不能直接用x和最终所求比较,所以用check函数计算避免浮点数
void dfs(int cur,int m, double x)
{
if( cur==depth)
{
if(check())
{
int i;
find=1;
printf("%d/%d=",a,b);
for(i=0; i<cur-1; i++)
printf("1/%d+",res[i]);
printf("1/%d",res[i]);
printf("\n");
}
return;
}
for(int i=m; i<=1000; i++)
{
res[cur] = i;
if(find) return;
if( ( n-(x+1/(double)i) )*i>(double)(depth-cur-1)) continue;
dfs(cur+1, i+1, x+1/(double)i);
}
}
//粗略估计目标层数第一个分数分母所能取的最大值b,然后向下递减求解,保证最先获得可行解中分母最大的结果
//迭代深搜保证最先获得个数最小的可行解
void ddfs()
{
int b=1.0/(n/depth);
for(int i=b; i>=2; i--)
{
res[0] = i;
if(find) return;
dfs(1, i+1, 1.0/i);
}
}
int main()
{
a=29;b=31;n=a/(double)b;
for(depth=2; depth<=1000; depth++)
{
memset(res,0,sizeof(res));
find=0;
ddfs();
if(find)
break;
}
getchar();
return 0;
}