zoukankan      html  css  js  c++  java
  • 算法笔记2

    分治法:是将待求解的原问题划分成若干个相互独立的子问题,通过求解子问题并将子问题的解合并,自底向上逐步求出原问题的解。
    动态规划法:是将待求解问题分解成若干个相互重叠的子问题,每个子问题对应决策过程的一个阶段,一般来说,子问题的重叠关系表现在对给定问题求解的递推关系(也就是动态规划函数)中,将子问题的解求解一次并填入表中,当需要再次求解此子问题时,可以通过查表获得该子问题的解而不用再次求解,从而避免了大量重复计算。
    共同点:是都将原问题分成若干个子问题
    不同点:动态规划法是将待求解问题分解成若干个相互重叠的子问题,而分治法是分解成若干个互不相交的子问题。


    蛮力法所赖的基本技术——扫描技术
    关键——依次处理所有元素
    基本的扫描技术——遍历
    (1)集合的遍历(2)线性表的遍历(3)树的遍历(4)图的遍历
    第四章 分治法
    一、分治法的设计思想
    将一个难以直接解决的大问题,划分成一些规模较小的子问题,以便各个击破,分而治之。更一般地说,将要求解的原问题划分成k个较小规模的子问题,对这k个子问题分别求解。如果子问题的规模仍然不够小,则再将每个子问题划分为k个规模更小的子问题,如此分解下去,直到问题规模足够小,很容易求出其解为止,再将子问题的解合并为一个更大规模的问题的解,自底向上逐步求出原问题的解。

    二、分治法的求解过程
    一般来说,分治法的求解过程由以下三个阶段组成:
    (1)划分:既然是分治,当然需要把规模为n的原问题划分为k个规模较小的子问题,并尽量使这k个子问题的规模大致相同。
    (2)求解子问题:各子问题的解法与原问题的解法通常是相同的,可以用递归的方法求解各个子问题,有时递归处理也可以用循环来实现。
    (3)合并:把各个子问题的解合并起来,合并的代价因情况不同有很大差异,分治算法的有效性很大程度上依赖于合并的实现。
    三、分治法所能解决的问题一般具有的几个特征是:
    (1)该问题的规模缩小到一定的程度就可以容易地解决;
    (2)该问题可以分解为若干个规模较小的相同问题,即该问题具有最优子结构性质;
    (3)利用该问题分解出的子问题的解可以合并为该问题的解;
    (4)原问题所分解出的各个子问题是相互独立的,即子问题之间不包含公共的子问题。

    章 动态规划法
    一、最优化问题:
    有n个输入,它的解由这n个输入的一个子集组成,这个子集必须满足某些事先给定的条件,这些条件称为约束条件,满足约束条件的解称为问题的可行解。满足约束条件的可行解可能不只一个,为了衡量这些可行解的优劣,事先给出一定的标准,这些标准通常以函数的形式给出,这些标准函数称为目标函数,使目标函数取得极值(极大或极小)的可行解称为最优解,这类问题就称为最优化问题。
    二、动态规划法的设计思想
    动态规划法将待求解问题分解成若干个相互重叠的子问题,每个子问题对应决策过程的一个阶段,一般来说,子问题的重叠关系表现在对给定问题求解的递推关系(也就是动态规划函数)中,将子问题的解求解一次并填入表中,当需要再次求解此子问题时,可以通过查表获得该子问题的解而不用再次求解,从而避免了大量重复计算。

    用动态规划法求解的问题具有特征:
    能够分解为相互重叠的若干子问题;
    满足最优性原理(也称最优子结构性质):该问题的最优解中也包含着其子问题的最优解。
    (用反证法)分析问题是否满足最优性原理:
    先假设由问题的最优解导出的子问题的解不是最优的;
    然后再证明在这个假设下可构造出比原问题最优解更好的解,从而导致矛盾。
    四、动态规划法利用问题的最优性原理:
    以自底向上的方式从子问题的最优解逐步构造出整个问题的最优解。
    动态规划法设计算法一般分成三个阶段:
    (1)分段:将原问题分解为若干个相互重叠的子问题;
    (2)分析:分析问题是否满足最优性原理,找出动态规划函数的递推式;
    (3)求解:利用递推式自底向上计算,实现动态规划过程。

    贪心法
    一、贪心法的设计思想
    贪心法在解决问题的策略上目光短浅,只根据当前已有的信息就做出选择,而且一旦做出了选择,不管将来有什么结果,这个选择都不会改变。换言之,贪心法并不是从整体最优考虑,它所做出的选择只是在某种意义上的局部最优。
    这种局部最优选择并不总能获得整体最优解(Optimal Solution),但通常能获得近似最优解(Near-Optimal Solution)。
    贪心算法的基本要素:具有2个重要性质:贪心选择性质和最优子结构性质。
    1.贪心选择性质:是指所求问题的整体最优解可以通过一系列局部最优的选择(即贪心选择)来达到。这是贪心算法可行的第一个基本要素,也是贪心算法与动态规划算法的主要区别。
    动态规划算法通常以自底向上的方式解各子问题
    贪心算法则通常以自顶向下的方式进行,以迭代方式作出相继的贪心选择,每作一次贪心选择就将所求问题简化为规模更小的子问题。

    对具体问题,要确定它是否具有贪心选择性质,必须证明每一步所作的贪心选择最终导致问题的整体最优解。 2.最优子结构性质
    当一个问题的最优解包含其子问题的最优解时,称此问题具有最优子结构性质。
    问题的最优子结构性质是该问题可用动态规划算法或贪心算法求解的关键特征。
    满足贪心选择性质必满足最优子结构性质。
    但是满足最优子结构性质却未必满足贪心选择性质。
    三、贪心算法与动态规划算法的差异
    共同点:贪心算法和动态规划算法都要求问题具有最优子结构性质。
    不同点:0-1背包问题和背包问题可以说明贪心算法与动态规划算法的主要差别。这2类问题都具有最优子结构性质,极为相似,但背包问题可以用贪心算法求解,而0-1背包问题却不能用贪心算法求解。

    动态规划法和贪心法:
    时间上:可达到多项式级别
    解决的问题:具有最优子结构性质
    那些不具有最优子结构性质的问题:
    往往需要蛮力法进行搜索:效率低
    改进:回溯法是对蛮力搜索算法的一种改进,它是一种系统地对问题的解空间进行搜索的算法,在搜索过程中,对解空间进行归约和修剪,使得其效率高于蛮力算法


    回溯法
    一、回溯法:是对蛮力搜索算法的一种改进,它是一种系统地对问题的解空间进行搜索的算法,在搜索过程中,对解空间进行归约和修剪,使得其效率高于蛮力算法
    二、解空间树的动态搜索(1)
    回溯法从根结点出发,按照深度优先策略遍历解空间树,搜索满足约束条件的解。在搜索至树中任一结点时,先判断该结点对应的部分解是否满足约束条件(可行解),或者是否超出目标函数(最优解)的界,也就是判断该结点是否包含问题的(最优)解,如果肯定不包含,则跳过对以该结点为根的子树的搜索,即所谓剪枝(Pruning);否则,进入以该结点为根的子树,继续按照深度优先策略搜索。
    (1)用约束条件剪去得不到可行解的子树;(2)用目标函数剪去得不到最优解的子树。
    这两类函数统称为剪枝函数(Pruning Function)。

    回溯法中常见的两类典型的解空间树是子集树和排列树。
    (1)子集树(Subset Trees):当所给问题是从n个元素的集合中找出满足某种性质的子集时,相应的解空间树称为子集树。在子集树中,|S1|=|S2|=…=|Sn|=c,即每个结点有相同数目的子树,通常情况下c=2,所以,子集树中共有2n个叶子结点,因此,遍历子集树需要Ω(2n)时间。例如, 0/1背包问题的解空间树是一颗子集树。
    (2)排列树(Permutation Trees):当所给问题是确定n个元素满足某种性质的排列时,相应的解空间树称为排列树。在排列树中,通常情况下,|S1|=n,|S2|=n-1,…,|Sn|=1,所以,排列树中共有n!个叶子结点,因此,遍历排列树需要Ω(n!)时间。例如, TSP问题的解空间树是一颗排列树。

    分支限界法
    一、.分支限界法与回溯法的异同点
    1.相同点:都是一种在问题的解空间树T中搜索问题解的算法。
    2.不同点:(1)求解目标不同;(2)搜索方式不同;(3)对扩展结点的扩展方式不同;(4)存储空间的要求不同。
    二、用分支限界法设计算法的步骤是:
    (1)针对所给问题,定义问题的解空间(对解进行编码);
    (2)确定易于搜索的解空间结构(按树或图组织解) ;
    (3)以广度优先或以最小耗费(最大收益)优先的方式搜索解空间,并在搜索过程中用剪枝函数避免无效搜索。
    三、 常见的两种分支限界法的算法框架

    分支限界法类似于回溯法,也是一种在问题的解空间树上搜索问题解的算法。
    但在一般情况下,分支限界法与回溯法的求解目标不同。
    回溯法的求解目标是找出T中满足约束条件的所有解;
    分支限界法的求解目标则是找出满足约束条件的一个解,或是在满足约束条件的解中找出使某一目标函数值达到极大或极小的解,即在某种意义下的最优解

    由于求解目标不同,导致分支限界法与回溯法在解空间树T上的搜索方式也不相同。
    回溯法以深度优先的方式搜索解空间树
    分支限界法以广度优先的方式搜索解空间树
    分支限界法的搜索策略是:在扩展结点处,先生成其所有的儿子结点(分支),然后再从当前的活结点表中选择下一个扩展对点。为了有效地选择下一扩展结点,以加速搜索的进程,在每一活结点处,计算一个函数值(限界),并根据这些已计算出的函数值,从当前活结点表中选择一个最有利的结点作为扩展结点,使搜索朝着解空间树上有最优解的分支推进,以便尽快地找出一个最优解。

    分支限界法首先确定一个合理的限界函数,并根据限界函数确定目标函数的界[down, up] 。
    按照广度优先策略遍历问题的解空间树,在分支结点上,依次搜索该结点的所有孩子结点,分别估算这些孩子结点的目标函数的可能取值:
    如果某孩子结点的目标函数可能取得的值超出目标函数的界,则将其丢弃,因为从这个结点生成的解不会比目前已经得到的解更好;否则,将其加入待处理结点表(以下简称表PT)中。
    依次从表PT中选取使目标函数的值取得极值的结点成为当前扩展结点,重复上述过程,直到找到最优解。

    分治法所能解决的问题一般具有以下几个特征: 1) 该问题的规模缩小到一定的程度就可以容易地解决 2) 该问题可以分解为若干个规模较小的相同问题,即该问题具有最优子结构性质。 3) 利用该问题分解出的子问题的解可以合并为该问题的解; 4) 该问题所分解出的各个子问题是相互独立的,即子问题之间不包含公共的子问题。 上述的第一条特征是绝大多数问题都可以满足的,因为问题的计算复杂性一般是随着问题规模的增加而增加; 第二条特征是应用分治法的前提它也是大多数问题可以满足的,此特征反映了递归思想的应用; 第三条特征是关键,能否利用分治法完全取决于问题是否具有第三条特征,如果具备了第一条和第二条特征,而不具备第三条特征,则可以考虑用贪心法或动态规划法。第四条特征涉及到分治法的效率,如果各子问题是不独立的则分治法要做许多不必要的工作,重复地解公共的子问题,此时虽然可用分治法,但一般用动态规划法较好。

     

     

  • 相关阅读:
    c++关于析构的那点小事(个人吐槽向
    我分析内存泄漏的一道作业题,已解决
    大一上学期的一点小疑惑,代码验证ok
    C++类型转换
    c++形参改变实参(对指针的理解
    c++整型->字符型转换
    [转]二重积分换元法的一种简单证明 (ps:里面的符号有点小错误,理解就好。。。
    c++实现矩阵类矩阵行列式,伴随矩阵,逆矩阵
    假期周计划2.0
    大道至简
  • 原文地址:https://www.cnblogs.com/wander-clouds/p/11037953.html
Copyright © 2011-2022 走看看