其实就是些正确的废话……没有很大的参考价值,但分类部分可以让思考更有条理一点
转载自https://blog.csdn.net/u010700335/article/details/44079069
一:剪枝策略的寻找的方法
1)微观方法:从问题本身出发,发现剪枝条件
2)宏观方法:从整体出发,发现剪枝条件。
3)注意提高效率,这是关键,最重要的。
总之,剪枝策略,属于算法优化范畴;通常应用在DFS 和 BFS 搜索算法中;剪枝策略就是寻找过滤条件,提前减少不必要的搜索路径。
二:剪枝算法(算法优化)
1、简介
在搜索算法中优化中,剪枝,就是通过某种判断,避免一些不必要的遍历过程,形象的说,就是剪去了搜索树中的某些“枝条”,故称剪枝。应用剪枝优化的核心问题是设计剪枝判断方法,即确定哪些枝条应当舍弃,哪些枝条应当保留的方法。
2、剪枝优化三原则: 正确、准确、高效.原则
搜索算法,绝大部分需要用到剪枝.然而,不是所有的枝条都可以剪掉,这就需要通过设计出合理的判断方法,以决定某一分支的取舍. 在设计判断方法的时候,需要遵循一定的原则.
剪枝的原则
1) 正确性
正如上文所述,枝条不是爱剪就能剪的. 如果随便剪枝,把带有最优解的那一分支也剪掉了的话,剪枝也就失去了意义. 所以,剪枝的前提是一定要保证不丢失正确的结果.
2)准确性
在保证了正确性的基础上,我们应该根据具体问题具体分析,采用合适的判断手段,使不包含最优解的枝条尽可能多的被剪去,以达到程序“最优化”的目的. 可以说,剪枝的准确性,是衡量一个优化算法好坏的标准.
3)高效性
设计优化程序的根本目的,是要减少搜索的次数,使程序运行的时间减少. 但为了使搜索次数尽可能的减少,我们又必须花工夫设计出一个准确性较高的优化算法,而当算法的准确性升高,其判断的次数必定增多,从而又导致耗时的增多,这便引出了矛盾. 因此,如何在优化与效率之间寻找一个平衡点,使得程序的时间复杂度尽可能降低,同样是非常重要的. 倘若一个剪枝的判断效果非常好,但是它却需要耗费大量的时间来判断、比较,结果整个程序运行起来也跟没有优化过的没什么区别,这样就太得不偿失了.
3、分类
剪枝算法按照其判断思路可大致分成两类:可行性剪枝及最优性剪枝.
3.1 可行性剪枝 —— 该方法判断继续搜索能否得出答案,如果不能直接回溯。
3.2 最优性剪枝
最优性剪枝,又称为上下界剪枝,是一种重要的搜索剪枝策略。它记录当前得到的最优值,如果当前结点已经无法产生比当前最优解更优的解时,可以提前回溯。
补完分类:转载自https://www.cnblogs.com/fenghaoran/p/6391016.html
1.可行性剪枝。
如果当前条件不合法就不再继续搜索,直接return。这是非常好理解的剪枝,搜索初学者都能轻松地掌握,而且也很好想。一般的搜索都会加上。
一般格式:
dfs(int x) { if(x>n)return; if(!check1(x))return; .... return; }
2.最优性剪枝。
如果当前条件所创造出的答案必定比之前的答案大,那么剩下的搜索就毫无必要,甚至可以剪掉。
我们利用某个函数估计出此时条件下答案的‘下界’,将它与已经推出的答案相比,如果不比当前答案小,就可以剪掉。
一般格式:
long long ans=987474477434487ll; ... Dfs(int x,...) { if(x... && ...){ans=....;return ...;} if(check2(x)>=ans)return ...; //最优性剪枝 for(int i=1;...;++i) { vis[...]=1; dfs(...); vis[...]=0; } }
一般实现:在搜索取和最大值时,如果后面的全部取最大仍然不比当前答案大就可以返回。
在搜和最小时同理,可以预处理后缀最大/最小和进行快速查询。
3.记忆化搜索。
记忆化搜索其实很像动态规划(DP)。
它的关键是:如果对于相同情况下必定答案相同,就可以把这个情况的答案值存储下来,以后再次搜索到这种情况时就可以直接调用。
还有就是不能搜出环来,不能互相依赖。
一般格式:
long long ans=987474477434487ll; ... Dfs(int x,...) { if(x... && ...){ans=....;return ...;} if(vis[x]!=0)return f[x];vis[x]=1; for(int i=1;...;++i) { vis[...]=1; dfs(...); vis[...]=0; f[x]=...; } }
4.搜索顺序剪枝
在一些迷宫题,网格题,或者其他搜索中可以贪心的题,搜索顺序显得十分重要。我经常听见有人说(我自己也说过):“从左边搜会T,从右边搜就A了”之类的语句。
其实在迷宫、网格类的题目中,以左上->右下为例,右下左上就明显比左上右下优秀。
在一些推断搜索题中,从已知信息最多的地方开始搜索显然更加优秀。
在一些题中,先搜某个值大的,再搜某个值小的(比如树的度数,产生答案的预计(A*)),速度明显会比乱搜更快。
搜索的复杂度明显讲不清,这种剪枝自然是能加就加。