迭代加深

迭代加深

迭代加深是用于优化搜索的,因为dfs的过程中是选择搜索的一个分支,不断地深入,直到我们达到递归的边界时才会返回。这样的话,如果搜索树的分支比较多,但答案在比较浅的分支节点时,一旦我们选择了错误的搜索分支,我们就会在错误的分支上搜索到很深的深度从而浪费搜索的时间。而迭代加深就是为了解决这一问题,迭代加深的思想是,限制我们搜索的最大深度,当我们在当前最大深度搜索不到答案时,再增大深度继续搜索,就这样一圈一圈向外扩展,有点类似bfs,但与bfs不同的时,不会存储一层的节点,空间复杂度仍然是O(h),(h是搜索树的高度)。

加成序列

#include <iostream>
#include <cstring>

using namespace std;

const int N = 110;
int path[N], n;

bool dfs(int u, int depth)
{
    if(u > depth)   return false;
    if(path[u - 1] == n)    return true;
    bool st[N] = {0};
    int s = 0;
    for(int i = u - 1; i >= 0; -- i)
        for(int j = i; j >= 0; -- j)
        {
            s = path[i] + path[j];
            if(s > n || s < path[u - 1] || st[s])   continue;
            path[u] = s;
            //标记一下排除等效冗余,因为可能两个数的相加是一样的,这样就是虽然过程不同,但得到的序列是一样的
            //所以需要剪枝排除不必要的
            st[s] = 1;
            if(dfs(u + 1, depth))   return true;
        }

    return false;
}

int main()
{
    while(cin >> n, n)
    {
        int depth = 1;
        path[0] = 1;
        while(!dfs(1, depth)) depth ++;
        for(int i = 0; i < depth; ++ i) cout << path[i] << ' ';
        cout << endl;
    }

    return 0;
}

双向搜索

送礼物

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;
typedef long long LL;

const int N = 46;

int w[N];
int weight[1 << 26], cnt = 1;
int n, m, k, ans;

//预处理前面k个物品并打表
void dfs1(int u, int s)
{
    //枚举到第k个物品,也就是终点
    if(u == k)
    {
        //将当前组合加入weight中
        weight[cnt ++] = s;
        return ;
    }
    //枚举不选择当前物品的情况
    dfs1(u + 1, s);
    //枚举选择当前物品的情况
    if((LL) s + w[u] <= m)  dfs1(u + 1, s + w[u]);
}

//后半部分搜索
void dfs2(int u, int s)
{
    //枚举到最后一个物品,搜索到终点
    if(u == n)
    {
        //在weight中查找最大的位置使weight <= m - s
        int l = 0, r = cnt - 1;
        while(l < r)
        {
            int mid = (l + r + 1) >> 1;
            if(weight[mid] <= m - s)    l = mid;
            else    r = mid - 1;
        }
        ans = max(ans, s + weight[l]);
        return;
    }

    dfs2(u + 1, s);
    if((LL)s + w[u] <= m)   dfs2(u + 1, s + w[u]);
}

int main()
{
    cin >> m >> n;
    for(int i = 0; i < n; ++ i) cin >> w[i];

    //优化一下搜索顺序
    sort(w, w + n);
    reverse(w, w + n);

    k = n / 2;
    dfs1(0, 0);

    sort(weight, weight + cnt);
    cnt = unique(weight, weight + cnt) - weight;

    dfs2(k, 0);
    cout << ans << endl;
    return 0;
}
posted @ 2023-01-15 14:47  cxy8  阅读(47)  评论(0编辑  收藏  举报