迭代加深搜搜索

对于可以用回溯法求解但解答树的深度没有明显上限的题目,可以考虑使用迭代加深搜索。
经典问题:埃及分数问题

给出一个分数,比如19/45,把它写成若干个形如1/Ri的分数的和的形式,比如19/45=1/5+1/6+1/18,要求分母不能重复使用并且使用的分数的个数最少。(如果有多组个数相同的解,最后的分数的分母越小越好,这对于题目来说是次要的。)
1、分母从小到大搜索
为了避免重复搜索
2、使用迭代加深搜索
求“步骤数最少”这类问题,基本上有两种似乎:广搜、迭代加深搜索。对于这道题来说,如果广搜将永远得不到结果,分母可以无限大!但是迭代加深搜索就比较好,虽然做了许多重复工作,但状态空间至少被限制住了。如果当前正在枚举的分母,使得接下来的选择即使每次都选择最大,达到最大深度的时候也不可能达到目标分数,那么当前正在枚举的分母及比它还大的分母,都不需要枚举了。这样可以给分母确定一个上界。另外,已经得到的结果加上当前枚举的分母对应的分数,要小于等于目标分数,这样给分母确定了一个下界(可以在O(1)的复杂度内确定这个下界)。

大神的代码~
int a, b;
int tree[1000];

bool dfs(int deep, int cb, int sa, int sb ) {
    tree[deep] = cb;
    int _a = sb + cb * sa;
    int _b = cb * sb;
    // 同一层向右平移, 找一个更小的分数。
    if ((_a * b) > (a * _b)) return dfs(deep, cb + 1, sa, sb); 
    // 递归边界:是否达到最大层数限制。
    if ( deep == 0 ) { 
        if ((_a * b) == (a * _b)) return true;
        else return false;
    }
    else return dfs( deep-1, 2, _a, _b);  // 移向下一层
    return false;
}

void iterativeDeepening() {
    int deep = 0;
    for (; deep <= 1000; deep++ ) {     // 迭代加深
        if (dfs(deep,2,0,1))  break; 
    }
    for (int i = 0; i <=deep; i++) {
        printf("1/%d ", tree[i]);
    }
}

int main () {
    while(scanf("%d%d",&a,&b) == 2){
        iterativeDeepening();
    }
    system("PAUSE");
    return 0;
}

你可能感兴趣的:(迭代加深搜搜索)