我们称呼分子为1的分数为埃及分数
对于把一个分数拆解成n个埃及分数相加的形式的方法肯定是多种多样的,例如 59/211 = 1/4 + 1/36 + 1/633 + 1/3798 = 1/6 + 1/9 + 1/633 + 1/3798.那么我们会选择哪种呢?
partychen告诉我们:
1.分解所需要的数越少越好
2.当1相同时,最后一个分数越大越好,即分母越小越好
3.当1,2相同时,这些分数的分母字典序越小越好。
那么现在就来思考算法了。很容易想到的思路。
现在有一个分数a/b。小于等于a/b的埃及分数有1/k, 1/(k+1), 1/(k+2).....
我们先将1/k拆分出去,然后继续拆分a/b - 1/k,如果我们发现这条路是行不通的。我们就试试先将1/(k+1)拆分出去,然后继续拆分a/b - 1/(k+2)。如果我们发现这条路还是行不通的,就换1/(k+3)........总是能找到答案的。
即拆分a/b,我们先尝试第一个小于等于a/b的埃及分数,再尝试第二个小于等于a/b的埃及分数,依次类推, 直到原分数拆分成0为止。
这种思路不就是dfs吗,它的解答树正好是按照深度优先的规则来遍历的。
想到这里我们就可以很高兴的写dfs了,但是写出来肯定会发现不对劲的。在写dfs之前我们应该先估计一下解答树的深度上限,不然有可能会爆栈。
对于这道题,我们每次都选择第一个小于它的埃及分数来拆分。首先我们要明白,任何一个分数总是能够找到第一个小于它的埃及分数的,换句话说解答树中的每个节点都有子节点。即解答树的深度是无穷大的。
如果我们陷入到了一种很坏的情况,虽然不至于搜索到无穷大,也会搜索到很深很深。这样是不可行的。
现在的问题在哪?dfs我们会搜索到很深。也就是解答树的深度没有明显的上界。这时候就要引入一种新的搜索方法,我们叫它迭代加深搜索。
迭代加深搜索和dfs基本相同,只不过我们限制了它的搜索的最大深度。假如一个分数最好的方案是拆解成三个埃及分数相加,其实也就是dfs我们要搜索三层。
那么按照迭代加深的思路,就是我们先限制搜索层数是0层,无解。1层,无解。2层,无解。3层,有解。只要这个解是存在的,通过深度不断增加的dfs,我们肯定可以找到它。
迭代加深有什么好处呢?
1.避免了因为深度没有明显上界,使得搜索很慢很慢的情况。
2.继承了dfs耗费空间少的特点。
3.因为我们设置了深度上限,在得知我们当前深度的情况下,我们可以利用已知信息剪枝。举个不恰当的例子,假如老师叫我们三天写1000道题目。我们有多种方法可以完成这个任务。按照a方法到了第二天晚上的时候,我们只做了50道。根据已有的上界:3天1000道题目,和我们当前的深度:直到第二天晚上只做了50道题目,还需要的任务量:6个小时做950道题目。我们就可以得出结论:这任务按照你之前的速度没法完成,要想完成老师的任务你要试试其他方法。比如我们可以试试b方法:直接copy同学作业,哈哈。
还有不懂的地方可以看一下网上关于迭代加深的讲解。代码如下:
#include
#include
#include
#include
#include
#include
#include
#include