算法导论精华总结 ~ 动态规划

  解释:动态规划(dynamic programming)与分治方法相似,都是通过组合子问题的解来求解原问题。

  优点:动态规划比分治方法高明之处在于对每个子子问题只求解一次,将其保存,无需重新计算。

  动态规划设计步骤:

    1. 刻画一个最优解的结构特征。
    2. 递归地定义最优解的值。
    3. 计算最优解的值,通常再用自底向上的方法。(维护一些额外信息,以便构造步骤4)
    4. 利用计算出的信息构造一个最优解。

钢条切割问题

  描述:给定一段长度为n英寸的钢条和一个价格表Pi(i = 1,2,...,n),求切割钢条的方案,使得销售收益Rn最大。

  价格表:

    长度i    1    2    3    4    5    6    7    8    9    10

    价格Pi    1    5    8    9    10  17  17   20  24  30

  

  我们可以明显看出来

    R1 = 1,切割方案1 = 1(无切割)

    R1 = 5,切割方案2 = 2(无切割)

    R1 = 8,切割方案3 = 3(无切割)

    R1 = 10,切割方案4 = 2 + 2

  由此可以总结出来一个公式Rn = max(Pn, R1 + Rn-1, R2 + Rn-2,..., Rn-1 + R1)

  由此可以写出自顶向下的递归实现伪代码

CUT-ROD(P,n)       //P为价格数组[1..n],n为长度为n的最大收益
    if n == 0          //如果n = 0 不会有收益,则返回0
        return 0

    q = -无穷          //把最大收益初始化为负无穷

    for i = 1 to n    //循环1到n的切割方式
        q = max(q,P[i] + CUT-ROD(P,n-i))  //最大收益等于当前收益或切割成n段的收益中的最大值

    return q           //返回最大收益

  递归的弊病:你会发现一个问题,这个计算非常的慢,在n=40的情况下,就基本得算好几分钟。之所以效率这么差的原因在于,这个函数反复计算相同的参数的递归调用。即反复求解相同的子问题。

  动态规划的实质:这时候就需要动态规划的出现了,动态规划会仔细安排求解顺序,对每个子问题只求解一次,并将结果保存下来。随后再次需要此子问题的解,只需要找保存的结果,而不必重新计算。因此归根结底,动态规划是付出额外的内存空间来节省计算时间,是典型的时空权衡。

动态规划的两种实现方法

  第一种  带备忘的自顶向下法

  第二种  自底向上法

  第一种仍然是递归,只不过加了一个数组来存储每个子问题的解。

  第二种就是从小问题解决,在逐渐推出大问题,类似于一道题的自然衍生过程。

  

  对于钢条切割的第一种方法伪代码

MEMOIZED-CUT-ROD(P,n)
    let r[0..n] be a new array //新建新的数组r
    for i = 0 to n //初始化r
        r[i] = -无穷
    return MEMOIZED-CUT-ROD-AUX(P,n,r) 

MEMOIZED-CUT-ROD-AUX(P,n,r)
    if r[n] >= 0 //如果r[n] >= 0说明这个切割算过一次,直接返回结果
        return r[n]
    if n == 0 //如果切割条数为0,则返回0
        q = 0
    else
        q = -无穷 //初始化
        for i = 1 to n
            q = max(q, P[i] + MEMOIZED-CUT-ROD-AUX(P, n-i, r)) //最优切割价格为当前价格或切割数为n-i的价格最大值
    r[n] = q //将最优切割值记录
    return q

  第二种方法的伪代码

BOTTOM-UP-CUT-ROD(P,n)
    let r[0..n] be a new array //新建r数组
    r[0] = 0     //初始化 0切割返回0
    for j = 1 to n  //循环从1条到n条长的最优解
        q = -无穷
        for i = 1 to j //循环从1切割到j切割的最优解
            q = max(q, P[i] + r[j-i]) //最优解q = 当前值或长度为i的价格和长度为j-i的最优解的和的最优值
        r[j] = q //记录最优解
    return q

  

时间: 2024-08-05 11:17:13

算法导论精华总结 ~ 动态规划的相关文章

算法导论三剑客之 动态规划 0-1背包问题

1 #include "iostream" 2 using namespace std; 3 4 float MAX(float m1,float m2){ 5 if(m1>=m2) 6 return m1; 7 else 8 return m2; 9 } 10 11 float bag_Zero_One(int n,float v,float p[],float w[]){ 12 if(n==0||v==0) 13 return 0; 14 else{ 15 float m2;

算法导论——lec 11 动态规划及应用

和分治法一样,动态规划也是通过组合子问题的解而解决整个问题的.分治法是指将问题划分为一个一个独立的子问题,递归地求解各个子问题然后合并子问题的解而得到原问题的解.与此不同,动态规划适用于子问题不是相互独立的情况,即各个子问题包含公共的子子问题.在这种情况下,如果用分治法会多做许多不必要的工作,重复求解相同的子子问题.而动态规划将每个子问题的解求解的结果放在一张表中,避免了重复求解. 一. 动态规划介绍 1. 动态规划方法介绍: 动态规划主要应用于最优化问题, 而这些问题通常有很多可行解,而我们希

【算法导论】用动态规划解活动选择问题

上一篇讲了贪心算法来解活动选择问题([算法导论]贪心算法之活动选择问题),发现后面有一道练习16.1-1是要用动态规划来解活动选择问题.其实跟之前的矩阵链乘法有些相似,也是考虑分割的活动是哪一个,并用二维数据来记录Sij---最大兼容集合个数,和用另一个二维数据来记录Sij取得最大时的活动分割点k.然后就是考虑边界问题,和使用递归来求动态规划的最优解. 代码注解比较详尽: #include <iostream> #include <algorithm> using namespac

《算法导论》中动态规划求解钢条切割问题

动态规划算法概述 动态规划(dynamic programming)1是一种与分治方法很像的方法,都是通过组合子问题的解来求解原问题.不同之处在于,动态规划用于子问题重叠的情况,比如我们学过的斐波那契数列.在斐波那契数列的求解问题中,我们经常要对一个公共子问题进行多次求解,而动态规划算法,则对每个子问题只求解一次,将其解保存在一个表格中,从而避免了大量的冗余计算量. 动态规划算法常用于寻找最优解问题(optimization problem).而其规划大概可分为四步: 1.刻画一个最优解的结构特

【算法导论之七】动态规划求解最长公共子序列

一.动态规划的概念 动态规划(Dynamic Programming)是通过组合子问题的解而解决整个问题的.分治算法是指将问题划分成一些独立的子问题,递归地求解各子问题,然后合并子问题的解而得到原始问题的解,与此不同,动态规划适用于子问题不是独立的情况,也就是各个子问题包含公共的子问题.在这种情况下,采用分治法会做许多不必要的工作,即重复地求解公共地子问题.动态规划算法对每个子问题只求解一次,将其结果保存在一张表中,从而避免每次遇到各个子问题时重新计算答案. 动态规划通常应用于最优化问题.此类问

算法导论_第十六章_动态规划_creatshare分享会

动态规划 注:该篇为本人原创,转载请注明出处:http://blog.csdn.net/chudongfang2015/article/details/51590817--开心 -.- 个人对动态规划的理解: 1.动态规划是一个付出额外空间来节省时间,就是所谓的空间换时间. 2.动态规划储存每个状态的最优解. 3.动态规划是用来把子问题的结果储存下来,再次用到的时候就不必再进行重复计算. 算法导论对动态规划的解释: 动态规划和分治方法相似,都是通过组合子问题的解来求解原问题,分治方法将问题划分为

算法导论--动态规划(装配线调度)

装配线问题: 某个工厂生产一种产品,有两种装配线选择,每条装配线都有n个装配站.可以单独用,装配线1或2加工生产,也可以使用装配线i的第j个装配站后,进入另一个装配线的第j+1个装配站继续生产.现想找出通过工厂装配线的最快方法. 装配线i的第j个装配站表示为Si,j,在该站的装配时间是ai,j 如果从 Si,j装配站生产后,转移到另一个生产线继续生产所耗费的时间为ti,j 进入装配线花费时间ei,完成生产后离开装配线所耗费时间为xi 令f*表示通过生产所有路线中的最快的时间 令fi[j]表示从入

《算法导论》读书笔记之第16章 0-1背包问题—动态规划求解

原文:http://www.cnblogs.com/Anker/archive/2013/05/04/3059070.html 1.前言 前段时间忙着搞毕业论文,看书效率不高,导致博客一个多月没有更新了.前段时间真是有些堕落啊,混日子的感觉,很少不爽.今天开始继续看算法导论.今天继续学习动态规划和贪心算法.首先简单的介绍一下动态规划与贪心算法的各自特点及其区别.然后针对0-1背包问题进行讨论.最后给出一个简单的测试例子,联系动态规划实现0-1背包问题. 2.动态规划与贪心算法 关于动态规划的总结

算法导论--动态规划(钢条切割)

钢条切割问题 现有一段长度为n英寸的钢条和一个价格表pi,求切割方案使销售利益最大rn最大 长度为n英寸的钢条共有2n?1种不同的切割方案,因为可以每个整英寸的位置都可以决定切割或者不切割. 为了得到rn最大,可以把这个问题分成子问题求解,先切一刀,再考虑余下的部分的最大收益即求 rn=max{pk+rn?k}(k=1,2,3-n-1), pk部分不进行继续切割,直接作为一个整体售出 ; rn?k部分继续切割,考虑所有的情况,分成子问题. 求出所有k值对应的收益最大者作为rn 也有可能不进行任何