迭代加深搜索

迭代加深搜索

为什么需要迭代加深?

先来上发讲解图:

 

迭代加深搜索
迭代加深搜索(Iterative Deepening Depth First Search,IDDFS),是朴素深度优先搜索(Depth First Search,DFS)的一种改进。它的核心思想是:控制当前搜索的深度上限
mxd,初始化为1,并令其不断递增,在这个深度限制上进行DFS

基本思想:以BFS的思想写DFS。

理解就是以BFS的思想写DFS。首先深度优先搜索k层,若没有找到可行解,再深度优先搜索k+1层,直到找到可行解为止。

由于深度是从小到大逐渐增大的,所以当搜索到结果时可以保证搜索深度是最小的。这也是迭代加深搜索在一部分情况下

可以代替广度优先搜索的原(还比广搜省空间)。

前提:
题目一定要有解,否则会无限循环下去。
好处:
1.时间复杂度只比BFS稍差一点(虽然搜索k+1层时会重复搜索k层,但是整体而言并不比广搜慢很多)。
2.空间复杂度与深搜相同,却比广搜小很多。
3.利于剪枝。

举例:埃及分数

Description

在古埃及,人们使用单位分数的和(形如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   ),编程计算最好的表达方式。

Input

一行包含a,b    (  0〈a〈b〈1000  )。

Output

每组测试数据若干个数,自小到大排列,依次是单位分数的分母。

Sample Input

19 45
Sample Output

5 6 18

1 分析

此题显然可以用搜索来解决,但是它的解答树是及其庞大的。你既无法预估它的深度(加数个数),也无法预估当前深度下解答树的广度(加数大小)。此时只能通过IDDFS来求解。

2 思路

设当前最大深度限制为mxd,定义DFS函数为dfs(d,c,8a,b),其中d为当前深度,a/b为当前剩余的分数,c为满足1/c⩽a/b的最小c
DFS的流程如下:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll a, b;
ll maxdep;
ll fm[1000010], ans[1000010];
 
//快读
inline ll read() {
    ll x = 0, f = 1; char ch = getchar();
    while (ch < '0' || ch > '9') {if (ch == '-') f = -1; ch = getchar();}
    while (ch >= '0' && ch <= '9') {x = x * 10 + ch - '0'; ch = getchar();}
    return x * f;
}
 
//最大公约数
ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;}
 
ll get_max(ll a, ll b) {for (ll i = 2; ; i++) if (a * i > b) return i;}
 
bool dfs(ll a, ll b, ll dep) {
    bool flag = 0;
    if (dep == maxdep) {
        if (b % a) return 0;
        fm[dep] = b / a;
        if (fm[dep] < ans[dep] || ans[0] == 0) {
            memcpy(ans, fm, sizeof fm);
        }
        return 1;
    }
    for (ll i = get_max(a, b); ; i++) {
        if ((maxdep - dep + 1) * b <= a * i) break;
        fm[dep] = i;
        ll d = gcd(a * i - b, b * i);
        if (dfs((a * i - b) / d, (b * i) / d, dep + 1)) flag = 1;
    }
    return flag;
}
 
int main() {
    a = read(), b = read();
    for (maxdep = 1; ; maxdep++) {//迭代加深
        memset(fm, 0, sizeof fm);
        memset(ans, 0, sizeof ans);//初始化
        if (dfs(a, b, 0)) {
            for (ll i = 0; i <= maxdep; i++) {
                if (i == 0) printf("%lld", ans[i]);
                else printf(" %lld", ans[i]);
            }
            return 0;
        }
    }
}

 

因上求缘,果上努力~~~~ 作者:每天卷学习,转载请注明原文链接:https://www.cnblogs.com/BlairGrowing/p/14093909.html

原文地址:https://www.cnblogs.com/BlairGrowing/p/14093909.html