当前位置: 首页 > news >正文

【转】搜索算法的剪枝优化

搜索算法按搜索的方式分有两类,一类是深度优先搜索,一类是广度优先搜索。我们知道,深度搜索编程简单,程序简洁易懂,空间需求也比较低,但是这种方法的 时间复杂度往往是指数级的,倘若不加优化,其时间效率简直无法忍受;而广度优先搜索虽然时间复杂度比前者低一些,但其庞大的空间需求量又往往让人望而却步。 所以,对程序进行优化,就成为搜索算法编程中最关键的一环。本文所要讨论的便是搜索算法中优化程序的一种基本方法叫“剪枝”。 一、what is it?       搜索的进程可以看作是从树根出发,遍历一棵倒置的树——搜索树的过程。而所谓剪枝,顾名思义,就是通过某种判断,避免一些不必要的遍历过程,形象的说,就是剪去了搜索树中的某些“枝条”,故称剪枝。应用剪枝优化的核心问题是设计剪枝判断方法,即确定哪些枝条应当舍弃,哪些枝条应当保留的方法。 二、剪枝的原则 原则之一:正确性。    因为它能够“剪去”搜索树中的一些“枝条”。然而,如果在剪枝的时候,将“长有”我们所需要的解的枝条也剪掉了,那么,一切优化也就都失去了意义。所以,对剪枝的第一个要求就是正确性,即必须保证不丢失正确的结果,这是剪枝优化的前提。我们利用“必要条件”来进行剪枝判断。也就是说,通过解所必须具备的特征、必须满足的条件等方面来考察待判断的枝条能否被剪枝。这样,就可以保证所剪掉的枝条一定不是正解所在的枝条。 原则之二:准确性。 即能够尽可能多的剪去不能通向正解的枝条。准确性可以说是剪枝优化的生命。 原则之三:高效性。 经常还需要提高判断操作本身的时间效率。 综上所述,我们可以把剪枝优化的主要原则归结为六个字:正确、准确、高效。 我们可以把常用的剪枝判断大致分成以下两类: 可行性剪枝。 最优性剪枝(上下界剪枝)。 三、可行性剪枝 搜索过程可以看作是对一棵树的遍历。在很多情况下,并不是搜索树中的所有枝条都能通向我们需要的结果,很多的枝条实际上只是一些死胡同。如果我们能够在刚刚进入这样的死胡同的时候,就能够判断出来并立即剪枝,程序的效率往往会得到提高。而所谓可行性剪枝,正是基于这样一种考虑。 下面我们举一个例子——Betsy的旅行(USACO)。 题目简述:一个正方形的小镇被分成N的平方个小方格,Betsy要从左上角的方格到达左下角的方格,并且经过每个方格恰好一次。编程对于给定的N,计算出Betsy能采用的所有的旅行路线的数目。 我们用深度优先的回溯方法来解决这个问题:Betsy从左上角出发,每一步可以从一个格子移动到相邻的没有到过的格子中,遇到死胡同则回溯,当移动了N2-1步并达到左下角时,即得到了一条新的路径,继续回溯搜索,直至遍历完所有道路。 但是,仅仅依照上述算法框架编程,时间效率极低,对N=6的情况无法很好的解决,所以,优化势在必行。对本题优化的关键就在于当搜索到某一个步骤时,能够提前判断出在后面的搜索过程中是否一定会遇到死胡同,而可行性剪枝正可以在这里派上用场。 我们首先从“必要条件”,即合法的解所应当具备的特征的角度分析剪枝的方法,主要有两个方向:对于一条合法的路径,除出发点和目标格子外,每一个中间格子都必然有“一进一出”的过程。所以在搜索过程中,必须保证每个尚未经过的可格子都与至少两个尚未经过的格子相邻(除非当时Betsy就在它旁边)。这里,我们是从微观的角度分析问题。 在第一个条件的基础上,我们还可以从宏观的角度分析,进一步提高剪枝判断的准确性。显然,在一个合法的移动方案的任何时刻,都不可能有孤立的区域存在。虽然孤立区域中的每一个格子也可能都有至少两个相邻的空的格子,但它们作为一个整体,Betsy已经不能达到。我们也应当及时判断出这种情况,并避免之。 以上两个剪枝判断条件都是正确的,其准确度也比较高。但是,仅仅满足这两点还不够,剪枝判断的操作过程还必须力求高效。假如我们在每次剪枝判断时,都简单的对N2个格子进行一遍扫描,其效率的低下可想而知。因此,我们必须尽可能的简化判断的过程。 实际上,由于Betsy的每一次移动,只会影响到附近的格子,所以每次执行剪枝判断时,应当只对她附近的格子进行检查:对于第一个剪枝条件,我们可以设一个整型标志数组,分别保存与每个格子相邻的没被经过的格子的数目,Betsy每次移动到一个新位置,都只会使与之相邻的至多4个格子的标志值发生变化,只要检查它们的标志值即可。而对于第二个剪枝条件,处理就稍稍麻烦一些。但我们仍然可以使用局部分析的方法,即只通过对Betsy附近的格子进行判断,就确定是否应当剪枝,下图简要说明了剪枝的原理: 1、搜索算法的剪枝优化 - 墨涵 - 墨涵天地

上图给出了可以剪枝的三种情况。由于Betsy到过的所有格子都一定是四连通的,所以每种情况下的两个白色的格子之间必定是不连通的,它们当中必然至少有一个是属于某个孤立区域的,都一定可以剪枝。 经过上述的优化,程序的时间效率有了很大的提高        在应用可行性剪枝的时候,首先要多角度全面分析问题的特点(本题就是从微观和宏观两个角度设计剪枝方法),找到尽可能多的可以剪枝的情况;同时,还必须注意提高剪枝的时间效率,所以我们使用了“局部判断”的方法,特别是在处理第二个剪枝条件时,更是通过局部判断来体现整体性质(是否有孤立区域),这一技巧不仅在设计剪枝方法的时候能够发挥作用,在其他方面也有着极为广泛的应用。 四 、最优性剪枝        在我们平时遇到的问题中,有一大类是所谓最优化问题,即所要求的结果是最优解。如果我们使用搜索方法来解决这类问题,那么,最优性剪枝是一定要考虑到的。       首先要作一些说明:我们知道,解的优劣一般是通过一个评价函数来评判的。这里定义一个抽象的评价函数——“优度”,它的值越大,对应的解也就越优(对于具体的问题,我们可以认为“优度”代表正的收益或负的代价等)。 然后,我们再来回顾一下搜索最优解的过程:一般情况下,我们需要保存一个“当前最优解”,实际上就是保存解的优度的一个下界。在遍历到搜索树的叶子节点的时候,我们就能得到一个新的解,当然也就得到了它的评价函数值,与保存的优度的下界作比较,如果新解的优度值更大,则这个优度值就成为新的下界。搜索结束后,所保存的解就是最优解。 那么,最优性剪枝又是如何进行的呢?当我们处在搜索树的枝条上时,可以通过某种方法估算出该枝条上的所有解的评价函数的上界,即所谓估价函数。显然,大于当前保存的优度的下界,是该枝条上存在最优解的必要条件,否则就一定可以剪枝。所以,最优性剪枝也可以称为“上下界剪枝”。同时,我们也可以看到,最优性剪枝的核心问题就是估价函数的建立。

转载于:https://www.cnblogs.com/lzhitian/archive/2012/05/05/2485434.html

相关文章:

  • vue.js过渡效果之--javascript钩子
  • 吓死猪队友 只用命令行登录Windows就问你怕不怕!
  • 从零开始学习Sencha Touch MVC应用之十四
  • 四 APPIUM GUI讲解(Windows版)(转)
  • net user使用
  • 如何在Ubuntu上使用Grafana监控Docker
  • 电脑快捷键
  • 字符合并[HAOI2016]
  • love——sir thomas browne
  • 开源 java CMS - FreeCMS2.6 积分记录
  • 个人记事本-介绍
  • 如何让Ubuntu在老旧设备上飞速运行!
  • Redis事件驱动库转
  • 开源 java CMS - FreeCMS2.6 站内信
  • Spring 整合 Hessian
  • 【Under-the-hood-ReactJS-Part0】React源码解读
  • Android 架构优化~MVP 架构改造
  • express + mock 让前后台并行开发
  • Nginx 通过 Lua + Redis 实现动态封禁 IP
  • Perseus-BERT——业内性能极致优化的BERT训练方案
  • PHP CLI应用的调试原理
  • PyCharm搭建GO开发环境(GO语言学习第1课)
  • sessionStorage和localStorage
  • 多线程事务回滚
  • 基于Vue2全家桶的移动端AppDEMO实现
  • 记一次和乔布斯合作最难忘的经历
  • 技术胖1-4季视频复习— (看视频笔记)
  • 前端相关框架总和
  • 深度学习入门:10门免费线上课程推荐
  • 突破自己的技术思维
  • 学习HTTP相关知识笔记
  • 优秀架构师必须掌握的架构思维
  • 智能合约Solidity教程-事件和日志(一)
  • LIGO、Virgo第三轮探测告捷,同时探测到一对黑洞合并产生的引力波事件 ...
  • 策略 : 一文教你成为人工智能(AI)领域专家
  • ​软考-高级-系统架构设计师教程(清华第2版)【第9章 软件可靠性基础知识(P320~344)-思维导图】​
  • #includecmath
  • #stm32整理(一)flash读写
  • (10)工业界推荐系统-小红书推荐场景及内部实践【排序模型的特征】
  • (11)工业界推荐系统-小红书推荐场景及内部实践【粗排三塔模型】
  • (Demo分享)利用原生JavaScript-随机数-实现做一个烟花案例
  • (react踩过的坑)Antd Select(设置了labelInValue)在FormItem中initialValue的问题
  • (备忘)Java Map 遍历
  • (转)Linq学习笔记
  • .[backups@airmail.cc].faust勒索病毒的最新威胁:如何恢复您的数据?
  • .aanva
  • .NET 8.0 中有哪些新的变化?
  • .NET BackgroundWorker
  • .NET CF命令行调试器MDbg入门(三) 进程控制
  • .NET MVC第五章、模型绑定获取表单数据
  • .Net下使用 Geb.Video.FFMPEG 操作视频文件
  • .NET学习教程二——.net基础定义+VS常用设置
  • .sh
  • /deep/和 >>>以及 ::v-deep 三者的区别
  • @Bean有哪些属性