动态规划法

动态规划的关键点

  • 最优原理
    也就是最优字结构性质。这指的的是一个最优化策略具有这样的性质,无论过去状态和决策如何,对前面的决策形成的状态而言,余下的决策必须构成最优策略,简单来说就是一个最优策略的子策略总是最优的,如果一个问题满足最优原理就称具有最优子结构性质。

  • 无后效性
    指的是某个状态下的决策的收益,只与状态和决策相关,与达到该状态的方式无关。

  • 子问题的重叠性
    动态规划将原来指数级的暴力搜索算法改进到了具有多项式时间复杂度的算法,其中的关键在于解决了冗余,重复计算的问题,知识动态规划算法的根本目的

动态规划算法的两种形式

举一个简单的例子:就斐波拉契数列Fibonacci

Fibonacci (n) = 1;   n = 0

Fibonacci (n) = 1;   n = 1

Fibonacci (n) = Fibonacci(n-1) + Fibonacci(n-2)

一、首先使用递归版本实现这个算法

public int fib(int n)
{
    if(n<=0)
        return 0;
    if(n==1)
        return 1;
    return fib( n-1)+fib(n-2);
}
//输入6
//输出:8

分析递归算法的执行流程,输入6,执行的递归树如图所示
动态规划法_第1张图片
上面的递归树中的每一个子节点都会执行一次,很多重复的节点被执行,fib(2)被重复执行了五次,由于调用每一个函数的时候都要保留上下文,所以空间上开销也不小。这么多的子节点被重复执行,如果在执行的时候把执行过的子节点保存起来,后面要用到的时候直接查表调用的话可以节约大量的时间。下面就看看动态规划的两种方法怎样来解决斐波拉契数列Fibonacci 数列问题。

二、自顶向下的备忘录法

public static int Fibonacci(int n)
{
        if(n<=0)
            return n;
        int []Memo=new int[n+1];        
        for(int i=0;i<=n;i++)
            Memo[i]=-1;
        return fib(n, Memo);
    }
    public static int fib(int n,int []Memo)
    {

        if(Memo[n]!=-1)
            return Memo[n];
    //如果已经求出了fib(n)的值直接返回,否则将求出的值保存在Memo备忘录中。               
        if(n<=2)
            Memo[n]=1;

        else Memo[n]=fib( n-1,Memo)+fib(n-2,Memo);  

        return Memo[n];
    }

创建了一个n+1大小的数组来保存求出的斐波拉契数列中的每一个值,在递归的时候如果发现前面的fib(n)的值计算出来就不再计算,如果未计算出来,则计算出来后保存在Memo数组中,下次在嗲用fib(n)的时候就不会重复递归了。
比如上面的递归树中fin(6)计算fib(5),调用fib(5)计算出了fib(4)后,fib(6)再嗲用fib(4)就不会递归fib(4)的子树了,因为fib(4)的值已经保存再Memo[4]中

三、自底向上的动态规划

备忘录法还是利用了递归,上面算法不管怎样,计算fib(6)的时候最后还是要计算出fib(1),fib(2),fib(3)……,那么何不先计算出fib(1),fib(2),fib(3)……,呢?这也就是动态规划的核心,先计算子问题,再由子问题计算父问题。

public static int fib(int n)
    {
        if(n<=1)
            return n;

        int Memo_i_2=0;
        int Memo_i_1=1;
        int Memo_i=1;
        for(int i=2;i<=n;i++)
        {
            Memo_i=Memo_i_2+Memo_i_1;
            Memo_i_2=Memo_i_1;
            Memo_i_1=Memo_i;
        }       
        return Memo_i;
    }

一般来说由于备忘录方式的动态规划方法使用了递归,递归的时候会产生额外的开销,使用自底向上的动态规划方法要比备忘录方法好。

你以为看懂了上面就懂动态规划了??那你就想的太简单了,动态规划问题远远不止,具体实例请看下次分析!

你可能感兴趣的:(【软考学习】)