标签:
这里我将对大部分的资料进行裁剪整理,并非原创。
动态规划是一种重要的程序设计思想,具有广泛的应用价值。使用动态规划思想来设计算法,对于不少问题往往具有高时效,因而,对于能够使用动态规划思想来解决的问题,使用动态规划是比较明智的选择。
能够用动态规划解决的问题,往往是最优化问题,且问题的最优解(或特定解)的局部往往是局部问题在相应条件下的最优解,而且问题的最优解与其子问题的最优解要有一定的关联,要能建立递推关系。如果这种关系难以建立,即问题的特定解不仅依赖于子问题的特定解,而且与子问题的一般解相关,那么,一方面难以记录下那么多的“一般解”,另一方面,递推的效率也将是很低的;此外,为了体现动态规划的高时效,子问题应当是互相重叠的,即很多不同的问题共享相同的子问题。(如果子问题不重叠,则宜使用其它方法,如分治法等。)
动态规划一般可以通过两种手段比较高效地实现,其一是通过自顶向下记忆化的方法,即通过递归或不递归的手段,将对问题最优解的求解,归结为求其子问题的最优解,并将计算过的结果记录下来,从而实现结果的共享;另一种手段,也就是最主要的手段,通过自底向上的递推的方式,由于这种方式代价要比前一种方式小,因而被普遍采用,下面的讨论均采用这种方式实现。动态规划之所以具有高时效,是因为它在将问题规模不断减小的同时,有效地把解记录下来,从而避免了反复解同一个子问题的现象,因而只要运用得当,较之搜索而言,效率就会有很大的提高。
动态规划的思想,为我们解决与重叠子问题相关的最优化问题提供了一个思考方向:通过迭代考虑子问题,将问题规模减小而最终解决问题。适于用动态规划解决的问题,是十分广泛的。动态规划的思想本身是重要的,但更重要的是面对具体问题的具体分析。要分析问题是否具备使用动态规划的条件,确定使用动态规划解题的子问题空间和递推关系式等,以及在(常规)内存有限的计算机上实现这些算法。下面分别就构思和实现两个方面进一步探讨动态规划这一思想。
首先,要大致分析一个问题是否可能用动态规划解决。如果一个问题难以确定子问题,或问题与其子问题的特殊解之间毫无关系,就要考虑使用其它方法来解决(如搜索或其它方法等)。做一个大概的判断是有必要的,可以防止在这上面白花时间。通常一个可以有效使用动态规划解决的问题基本上满足以下几方面的特性:
1、 子问题的最优解仅与起点和终点(或有相应代表意义的量)有关而与到达起点、终点的路径无关。
2、 大量子问题是重叠的,否则难以体现动态规划的优越性。
阶段:将所给问题的过程,按时间或空间特征分解成若干相互联系的阶段,以便按次序去求每阶段的解。常用字母k表示阶段变量。[1]
阶段是问题的属性。多阶段决策问题中通常存在着若干个阶段,如上面的例子,就有A、B、C、D这四个阶段。在一般情况下,阶段是和时间有关的;但是在很多问题(我的感觉,特别是信息学问题)中,阶段和时间是无关的。从阶段的定义中,可以看出阶段的两个特点,一是“相互联系”,二是“次序”。
阶段之间是怎样相互联系的?就是通过状态和状态转移。
状态:各阶段开始时的客观条件叫做状态。描述各阶段状态的变量称为状态变量,常用sk表示第k阶段的状态变量,状态变量sk的取值集合称为状态集合,用Sk表示。[1]
状态是阶段的属性。每个阶段通常包含若干个状态,用以描述问题发展到这个阶段时所处在的一种客观情况。在上面的例子中,行人从出发点A1走过两个阶段之后,可能出现的情况有三种,即处于C1、C2或C3点。那么第三个阶段就有三个状态S3={C1,C2,C3}。
每个阶段的状态都是由以前阶段的状态以某种方式“变化”而来,这种“变化”称为状态转移(暂不定义)。上例中C3点可以从B1点过来,也可以从B2点过来,从阶段2的B1或B2状态走到阶段3的C3状态就是状态转移。状态转移是导出状态的途径,也是联系各阶段的途径。
说到这里,可以提出应用动态规划的一个重要条件。那就是将各阶段按照一定的次序排列好之后,对于某个给定的阶段状态,它以前各阶段的状态无法直接影响它未来的发展,而只能通过当前的这个状态。换句话说,每个状态都是“过去历史的一个完整总结[1]”。这就是无后效性。对这个性质,下文还将会有解释。
标签:
原文地址:http://www.cnblogs.com/TenderRun/p/5258827.html