/*
算法竞赛入门经典 例题7-2 埃及分数
隐式图迭代加深搜索。
关键点1: 解答树模型
第0层根
第1层节点分别为1/2,1/3,1/4,1/5 ...
第2层 (1/2)节点的子节点为 1/2+1/3, 1/2+1/4, 1/2+1/5... (1/3)的子节点为1/3+1/4, 1/3+1/5...
第3层 (1/2+1/3)节点的子节点为 1/2+1/3+1/4, 1/2+1/3+1/5...
...
关键点2: 去枝(见原书)
关键点3: 路径记录,使用stl stack保存返回路径。
*/
#include <iostream>
#include <string>
#include <cstdio>
#include <cmath>
#include <stack>
using namespace std;
const int MAX = 1000;
int a, b;
double goal; // a/b对应的double类型值
int max_lvl; // 当前搜索的最大深度
stack<int> s; // 栈用来保存返回路径
//迭代加深搜索
//lvl:当前层数, st:开始数字, sum:父节点值
int iter_deep(int lvl, int st, double sum)
{
int ok = (lvl == max_lvl);
for(int i=st; 1; i++) {
double temp = sum;
temp += 1.0/i;
if(temp + (max_lvl-lvl)*1.0/i + 1e-6 < goal) break;
if(temp - 1e-6 > goal) continue;
if(ok) {
if(fabs(goal-temp) < 1e-6) {
s.push(i);
return 1;
}
} else {
if(iter_deep(lvl+1, i+1, temp)) {
s.push(i);
return 1;
}
}
}
return 0;
}
int main(void) {
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
#endif
while(scanf("%d%d", &a, &b) == 2) {
goal = (double)a/b;
int ok = 1;
for(int i=1; i<MAX; i++) {
max_lvl = i;
if((ok = iter_deep(1, 2, 0))==1) break;
}
if(ok) {
printf("%d/%d = ", a, b);
while(s.size()) {
printf("1/%d", s.top());
s.pop();
if(s.size()) printf(" + ");
}
printf("\n");
}
}
return 0;
}
测试数据
2 3
10 21
19 45
53 64