动态规划

一.动态规划含义:

在现实生活中,有一类活动的过程,由于它的特殊性,可将过程分成若干个互相联系的阶段,在它的每一阶段都要做出决策,从而使整个过程达到最好的活动效果.因此,各个阶段决策确定后,组成一个决策序列,因而也就确定了整个过程的一条活动路线.这种把一个问题看作是一个前后关联具有链状结构的多阶段过程,就称为多阶段决策过程,这种问题称为多阶段决策问题. 在多阶段决策问题中,各个阶段采取的决策,一般来说是和时间有关的,决策依赖于当前状态,又随即引起状态的转移,一个决策序列就是在变化的状态中产生出来的,故有"动态"的含义,我们称这种解决多阶段决策最优化的过程为动态规划.

二.动态规划特征

动态规划的显著特征是:无后效性,有边界条件,且一般划分为很明显的阶段. 动态规划一般还存在一条或多条状态转移方程.

三。动态规划适用条件

  任何思想方法都有一定的局限性,超出了特定条件,它就失去了作用。同样,动态规划也并不是万能的。适用动态规划的问题必须满足最优化原理和无后效性。

  • 1.最优化原理(最优子结构性质)
    • 最优化原理可这样阐述:一个最优化策略具有这样的性质,不论过去状态和决策如何,对前面的决策所形成的状态而言,余下的诸决策必须构成最优策略。简而言之,一个最优化策略的子策略总是最优的。一个问题满足最优化原理又称其具有最优子结构性质。
  • 2.无后向性
    • 将各阶段按照一定的次序排列好之后,对于某个给定的阶段状态,它以前各阶段的状态无法直接影响它未来的决策,而只能通过当前的这个状态。换句话说,每个状态都是过去历史的一个完整总结。这就是无后向性,又称为无后效性。
  • 3.子问题的重叠性
    • 动态规划将原来具有指数级复杂度的搜索算法改进成了具有多项式时间的算法。其中的关键在于解决冗余,这是动态规划算法的根本目的。

  动态规划实质上是一种以空间换时间的技术,它在实现的过程中,不得不存储产生过程中的各种状态,所以它的空间复杂度要大于其它的算法。

应用一:问题具有重叠子问题    

  // 利用空间来换取时间,提高效率
        public static long FibDriver(int n)
        {
            long[] fib = new long[n +1];
            fib[0] = 0;
            fib[1] = 1;

            for (int t = 2; t <= n; t++)
            {
                fib[t] = -1;
            }
            return FibValue(fib,n);
        }

        // 方法一: 自顶而下,记忆化求解.利用递归
        private static long FibValue(long[] fib, int n)
        {
            if (fib[n] == -1)
            {
                fib[n] = FibValue(fib, n - 1) + FibValue(fib, n - 2);
            }

            return fib[n];
        }

        // 方法二: 自底而上,顺序求解.(利用迭代原因)
        private static long FibValue(int n)
        {
            long[] fib = new long[n + 1];
            fib[0] = 0;
            fib[1] = 1;

            for (int i = 2; i <= n; i++)
            {
                fib[i] = fib[i - 1] + fib[i - 2];
            }

            return fib[n];
        }


        // 方法三: 自底而上,顺序求解。空间优化
        private static long NewFibValue(int n)
        {
            long back1= 0, back2=1;
            long next = 0;

            if (n <= 0)
            {
                return 0;
            }           

            for (int i = 2; i <= n; i++)
            {
                next = back1 + back2;
                back1 = back2;
                back2 = next;
            }

            return next;
        }

 

  

 

 

       

 

posted on 2013-12-20 13:22  higirle  阅读(681)  评论(0编辑  收藏  举报