深搜的剪枝技巧

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

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

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

什么是剪枝

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

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

剪枝的原则

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;
}

自己领悟吧

原文地址:https://www.cnblogs.com/lcezych/p/10990200.html

时间: 2024-11-08 00:12:30

深搜的剪枝技巧的相关文章

一本通例题埃及分数—题解&amp;&amp;深搜的剪枝技巧总结

一.简述: 众所周知,深搜(深度优先搜索)的时间复杂度在不加任何优化的情况下是非常慢的,一般都是指数级别的时间复杂度,在题目严格的时间限制下难以通过.所以大多数搜索算法都需要优化.形象地看,搜索的优化过程就像将搜索树上没用的枝条剪下来,因此搜索的优化过程又叫剪枝.剪枝的实质就是通过判断决定是否要沿当前枝条走下去. 二.搜索的剪枝必需遵循三个原则: 1.正确性(不能把正解排除,要不然搜什么呢?)2.准确性(尽可能把不能通向正解的枝条剪去)3.高效性(因为在每个枝条上都要进行一次判断,如果判断的复杂

hdu1455 Sticks 深搜 强剪枝

Sticks Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 6035    Accepted Submission(s): 1704 Problem Description George took sticks of the same length and cut them randomly until all parts becam

【深搜加剪枝五】HDU 1010 Tempter of the Bone

Tempter of the BoneTime Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 64326    Accepted Submission(s): 17567 Problem Description The doggie found a bone in an ancient maze, which fascinated him a l

回溯深搜与剪枝初步

回溯算法也称试探法,一种系统的搜索问题的解的方法,是暴力搜寻法中的一种.回溯算法的基本思想是:从一条路往前走,能进则进.回溯算法解决问题的一般步骤: 根据问题定义一个解空间,它包含问题的解 利用适于搜索的方法组织解空间 利用深度优先法搜索解空间,并且在搜索过程中用剪枝函数避免无效搜索 回溯法采用试错的思想,它尝试分步的去解决一个问题.在分步解决问题的过程中,当它通过尝试发现现有的分步答案不能得到有效的正确的解答的时候,它将取消上一步甚至是上几步的计算,再通过其它的可能的分步解答再次尝试寻找问题的

深搜优化剪枝

之前做过不少深搜题,很多TLE,所以剪枝很重要,如何“未雨绸缪”,避免不必要的搜索树分支? 例题: 数的划分 将整数n分成k份,且每份不能为空,任意两份不能相同(不考虑顺序). 例如:n=7,k=3,下面三种分法被认为是相同的. 1,1,5: 1,5,1: 5,1,1: 问有多少种不同的分法. 输出一个整数,即不同的分法. 由题意得,其分发出现重复数字组合则为同一种算法,那么保证1-k个数递增即可 代码: #include<bits/stdc++.h> using namespace std;

深搜+DP剪枝 codevs 1047 邮票面值设计

codevs 1047 邮票面值设计 1999年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description 给定一个信封,最多只允许粘贴N张邮票,计算在给定K(N+K≤40)种邮票的情况下(假定所有的邮票数量都足够),如何设计邮票的面值,能得到最大值MAX,使在1-MAX之间的每一个邮资值都能得到. 例如,N=3,K=2,如果面值分别为1分.4分,则在1分-6分之间的每一个邮资值都能得到(当然还有8分.9分和1

HDOJ/HDU Tempter of the Bone(深搜+奇偶性剪枝)

Problem Description The doggie found a bone in an ancient maze, which fascinated him a lot. However, when he picked it up, the maze began to shake, and the doggie could feel the ground sinking. He realized that the bone was a trap, and he tried despe

HDU--1010 Tempter of the Bone(深搜+奇偶剪枝)

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1010 我认为的剪枝就是在本来的代码中加入一些附加条件使之不去进行多余的计算,防止超时 奇偶剪枝的知识链接 AC代码: 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 using namespace std; 5 int n,m,t,k,flag,starex,starey,endx,endy

HDU 1010 深搜+奇偶剪枝

题目:http://acm.hdu.edu.cn/showproblem.php?pid=1010 贴个资料: http://acm.hdu.edu.cn/forum/read.php?tid=6158 奇偶剪枝: 对于从起始点 s 到达终点 e,走且只走 t 步的可达性问题的一种剪枝策略. 如下列矩阵 : 从任意 0 到达 任意 0,所需步数均为偶数,到达任意 1 ,均为奇数.反之亦然 所以有,若s走且只走 t 步可到达e,则必有t >= abs(s.x - e.x) + abs(s.y -