剪枝

剪枝

剪枝是搜索中很重要的一个环节, 尽早排除搜索树中不必要的分支。

优化搜索顺序

优先搜索分支数量较小的节点

排除等效冗余

比如从n个物品选m个物品,选1,2和选2,1是一样的,这样我们只需要遍历其中一个即可,如果不考虑顺序的话尽量按组合的顺序搜索

可行性剪枝

当我们搜索状态在进行中发现不合法了就可以提前退出

最优性剪枝

在最优性问题中,我们在搜索时发现,当前正在搜索的答案,已经比我们已经搜索到的答案差的话,就可以提前退出

记忆化

多用在实现dp中,将已经遍历过的状态进行记录,不用重复访问同一状态

例1

小猫爬山

这道题目用到了优化搜索顺序,可行性剪枝和最优化剪枝,详细见代码里面的注释

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

using namespace std;
const int N = 20;
int a[N], cap[N];
int n, m, ans = N;

void dfs(int u, int cnt)
{
    //最优化剪枝:当前答案已经大于我们已经搜到的最优解
    if(cnt >= ans)    return;
    //找到了新的一组解,并且当前解是比已经搜到的最优解更优,更新最优解
    if(u == n)
    {
        ans = cnt;
        return;
    }
    
    for(int i = 0; i < cnt; ++ i)
        //可行性剪枝,当前答案已经非法
        if(cap[i] + a[u] <= m)  
        {
            cap[i] += a[u];
            dfs(u + 1, cnt);
            cap[i] -= a[u];
        }
    
    cap[cnt] = a[u];
    dfs(u + 1, cnt + 1);
    cap[cnt] = 0;
}

int main()
{
    cin >> n >> m;
    for(int i = 0; i < n; ++ i) cin >> a[i];
    
    //优化搜索顺序,放重量较大的,搜索树的分支会更小
    sort(a, a + n);
    reverse(a, a + n);
    dfs(0, 0);
    
    cout << ans << endl;
    return 0;
}

posted @ 2022-12-22 17:23  cxy8  阅读(25)  评论(0编辑  收藏  举报