• 深搜的剪枝技巧


    众所周知,搜索是个好东西,他能在很多时候(就是你不会正解打暴力的时候)派上用场。

    然而搜索的时间复杂度实在是太高了,大多数都是指数级别的,这让人很是头疼

    那么我来总结一下对搜索进行优化的技巧:剪枝

    什么是剪枝

    我们知道,搜索的进程可以看做遍历一棵搜索树的过程。而所谓的剪枝,就是通过某种判断,避免一些不必要的遍历过程。

    形象的来说,就是剪掉搜索树上的一些枝条来达到减少遍历次数,缩短时间复杂度的效果

    剪枝的原则

    1.正确性

    • 废话,你剪枝都把正确的答案剪了你还搜个啥呢?

    2.准确性

    • 尽可能多的剪去不需要的枝条,这样能够最大限度的优化搜索

    3.高效性

    • 由于你剪枝之前都要判断是否可以剪枝,所以判断的复杂度当然很重要。
    • 如果你判断的复杂度都爆了,那你还剪什么枝?

    然后就会出现一个矛盾。

    我们如果想要尽可能优的剪枝,就必须提高判断的准确性,就是尽可能只要一发现就剪去,这就常常会提高判断的复杂度,同时就降低了剪枝的效率

    但是如果剪枝消耗的时间过多,就会降低判断的准确性所带来的优化

    所以我们很多时候都要考虑这两者之间的关系,看看如何处理

    剪枝的技巧

    1.优化搜索顺序

    • 在很多时候,不同的搜索顺序往往会产生不同形状的搜索树,而我们就需要尽可能的优化搜索树的形态

    2.排除等效冗余

    • 有的时候我们可以从不同的分支到达同一个结果,那么这样的分支显然就只需要通过一次就可以了

    3.可行性剪枝

    • 简单的来说就是尽可能早的发现不可能的情况并进行剪枝,也就是在判断的时候进行优化
    • 有的时候这个限制条件会以区间的形式出现,所以它也叫做“上下界剪枝”

    4.最优性剪枝

    • 在最优化问题的过程中,如果当前的代价已经小于目前搜索到的最优解,显然就不用继续下去了,那么我们可以停止搜索,直接回溯

    5.记忆化

    • 可以消耗空间来换取时间,就是记录每个状态的搜索结果,这样在遍历时就可以直接查询了。
    • 目前的比赛一般都是空间足够,时间卡得很紧,所以用空间来换取时间的方法是可取的(毕竟都说T成狗,你什么时候听说过M成狗的

    我们来看一个比较简单的例题

    数的划分:传送门

    这道题最简单的方法显然就是一位一位的枚举,然后判断是否成立,是否和之前的情况重合。

    显然会TLE

    但是我们发现这个东西是不考虑顺序的,也就是说我们可以指定一个顺序,然后只要存储下来个数就可以了

    不妨将方案从小到大,所以拓展节点时的下界就是前一个节点

    上界是什么?

    假设我们已经枚举到了第n-1个点,正在枚举第n个点,由于后一个数都是大于等于前一个数的

    所以取最极端的情况,就是第n-1个数后面的所有数都相等,这时求平均数,显然就是第n个数的上界,因为它无论如何也不可能突破这个上界的

    搜索的代码还是比较好些的

    这里再提供另一种做法

    #include<cstdio>
    #include<iostream>
    #include<cstdlib>
    #include<iomanip>
    #include<cmath>
    #include<cstring>
    #include<string>
    #include<algorithm>
    using namespace std;
    int n,k,f[201][7];  
    int main(){
        cin>>n>>k;
        for (int i=1;i<=n;i++) {f[i][1]=1;f[i][0]=1;}
        for (int j=2;j<=k;j++) {f[1][j]=0;f[0][j]=0;}  
        for (int i=2;i<=n;i++)
            for (int j=2;j<=k;j++)
                if (i>j) f[i][j]=f[i-1][j-1]+f[i-j][j];
                else f[i][j]=f[i-1][j-1];
        cout<<f[n][k];
        return 0;
    }

    自己领悟吧

  • 相关阅读:
    javascript package的一种简单"优雅"实现
    高效、快速、专业的外科手术团队
    贝塞尔曲线
    经典格斗游戏《街头霸王》的Javascript实现
    该死的痘痘
    同步/异步与阻塞/非阻塞的区别
    Shell echo用法
    凹凸Linux面试题
    VMware Workstation 9下安装Fedora 18教程(转)
    Linux中locale 详解(转)
  • 原文地址:https://www.cnblogs.com/lcezych/p/10990200.html
Copyright © 2020-2023  润新知