算法分析与设计C++ 总结(三)
递归与分治
任何一个可以用计算机求解的问题所需的计算机时间都与其规模n有关。问题的规模越小,越容易直接求解,解题所需的计算时间也就越小。例如,对于n个元素的排序问题,当n=1时,不需要任何计算;n=2时,只要作一次比较即可排好序;n=3时只要作3次比较即可…。当n较大时,问题就不那么容易处理了。要想直接解决一个规模较大的问题,有时是相当困难的。分治法的设计思想是,讲一个难以直接解决的大问题分割成一些规模较小的相同问题,以便各个击破,分而治之。
如果原问题可分割成k个子问题(1<k<=n),且这些子问题都可解,并可利用这些子问题的解求出原问题的解,那么这种分治法就是可行的。由分治法产生的子问题往往是原问题的较小模式,这就为使用递归技术提供了方便。在这种情况下,反复应用分治手段,可以使子问题与原问题类型一致而其规模却不断缩小,最终使子问题缩小到很容易直接求出其解。由此自然导致递归算法的产生。
动态规划
动态规划的基本思想
动态规划算法通常用于求解具有某种最优性质的问题。在这类问题中,可能会有许多可行解。每一个解都对应于一个值,我们希望找到具有最优值得解,动态规划算法与分治法类似,其基本思想也是将待求解问题分解成若干个子问题,先求解子问题,经分解得到的子问题往往不是互相独立的。若用分治法来解决这类问题,则分解得到的子问题数目太多,有些子问题被重复计算了很多次。如果我们能够保存已解决的子问题的答案,而在需要时再找出已求得的答案,这样就可以避免大量的重复计算,节省时间。我们可以用一个表来自记录所有已解的子问题的答案。不管孩子问题以后是否被用到,只要它被计算过,就将其结果填入表中,这就是动态规划算法的基本思路。
设计动态规划算法的步骤
(1)找出最优解的性质,并刻画其结构特征;
(2)递归地定义最优解(写出动态规划方程);
(3)以自底向上的方式计算出最优解;
(4)根据计算最优值时得到的信息,构造一个最优解。
动态规划问题的特征
动态规划算法的有效性依赖于问题本身所具有的两个重要的性质:最优子结构性质和子问题重叠性质。
(1)最优子结构:当问题的最优解包含了其子问题的最优解时,称该问题具有最优子结构性质。
(2)重叠子问题:在用递归算法自顶向下解问题时,每次产生的子问题并不是总是新问题,有些子问题被反复计算多次。动态规划算法正式利用了这种子问题的重叠性质,对每一个子问题只解一次
。而后将其解保存一个表中,在以后尽可能多地利用这些子问题的解。
贪心算法
在求解最优解问题的过程中,依据某种贪心标准,从问题的初始状态触发,直接去求每一步的最优解,通过若干次的贪心选择,最终得出整个问题的最优解,这种求解方法就是贪心算法。从贪心算法的定义可以看出,贪心法并不是从整体上考虑问题,它所做出的选择只是在某种意义上的局部最优解,而由问题自身的特性决定了该题目运用贪心算法可以得到的最优解。贪心算法所做的选择可以依赖于以往所做过的选择,但绝不依赖于将来的选择,一部依赖于子问题的解,因此贪心算法所做的选择可以依赖于以往所做过的选择,但绝不依赖于将来的选择,也不依赖于子问题的解,因此贪心算法与其他算法相比具有一定的速度优势。如果一个问题可以同时用几种方法解决,贪心算法应该是最好的一个选择之一。
当一个问题具有最优子结构性质和贪心选择性质时,贪心算法通过一系列的选择来得到同一个问题的解。它所做的每一个选择都是在当前状态下具有某种意义的最好的选择,即贪心算法。尽管贪心算法对许多问题不能总是产生整体最优解,但对诸如最短路径问题、最小生成树问题以及哈夫曼编码问题等具有最优子结构和贪心选择性质的问题却可以获得整体最优解,而且所给出的算法一般比动态规划算法更加简单、直观和高效。
回溯算法
回溯法是一种组织搜索的一般技术,有“通用的结题法”之称,用它可以系统地搜索一个问题的所有解或任意解。
有许多问题,当需要找出它们的解集或者要求回答什么解是满足某些约束条件的最佳解时,往往要使用回溯法。它可以系统地搜索一个问题的所有解或任意解,既有系统性又有跳跃性。回溯法的基本做法是搜索,它是一种组织得井井有条的,能避免不必要搜索的穷举式搜索法。这种以深度优先的方式系统地搜索问题的解得方法称为回溯法。
回溯法在问题的解空间树种,按深度优先策略,从根节点触发搜索解空间树。算法搜索至解空间树的任一结点时,先判断该结点是否包含问题的解。如果肯定不包含,则跳过多以该店为根的子树的搜索,逐层向其祖先结点回溯。否则,进入该子树,继续按深度优先策略搜索。回溯法计算问题的所有解时,要回溯到根,且根结点的所有子树都已经被搜索完成才结束。回溯法求解问题的一个解时,只要搜索到问题的一个解就结束。
分支限界算法
分支限界算法把问题的可行解展开如树的分支,再经由各个分支寻找最佳解。分支限界算法在运筹学中应用于求解整数规划(或者混合整数规划)问题,可大大减少需要计算的方案数目。
分支限界法是一个用途十分广泛的算法,运用这种算法的技巧性很强,不同类型的问题解法也各不相同。分支限界算法的基本思想是对有约束条件的最优化问题的所有可行解(数目有限)空间进行搜索。该算法在具体执行时,把全部可行的解空间不断分割为越来越小的子集(称为分支),并为每个子集内的解的值计算一个下界或上界(称为限界)。在每次分支后。对凡是界限超出已知可行解值那些子集不再做进一步的分支。这样,解的许多子集(即搜索树上的许多结点)就可以不予考虑,从而缩小了搜索范围。这一过程一直进行到找出可行解为止,该可行解的值不大于任何子集的界限。因此这种算法一般可以求得最优解。