动态规划算法详解(基本思想步骤及经典例子)

动态规划算法详解(基本思想步骤及经典例子)-mikechen

动态规划算法简介

动态规划,英文名Dynamic Programming,是一种把原问题分解为相对简单的子问题以求解的方法。

动态规划为了避免多次解决重复的子问题,子问题的结果都被保存,直到整个问题得以解决。

动态规划算法:每次决策依赖于当前状态,个决策序列就是在变化的状态中产生出来的,所以,这种多阶段最优化决策解决问题的过程就称为动态规划。

 

动态规划算法基本思想

动态规划算法的思想比较简单,其实质是分治思想和解决冗余,因此它与分治法和贪心法类似。

动态规划是把原问题分解为若干子问题,自底向上,先求解子问题,把结果存储在表格中。

在求解大问题时直接从表格中查询小问题的解,避免重复计算,从而提高算法效率。

 

动态规划算法步骤

动态规划的设计都有着一定的模式,一般要经历以下4个步骤:

1)划分阶段

按照问题的特征,把问题分为若干阶段,划分后的阶段一定是有序的或者可排序的。

 

2)确定状态和状态变量

将问题发展到各个阶段时所处的各种不同的客观情况表现出来。状态的选择要满足无后续性。

 

3)确定决策并写出状态转移方程

状态转移就是根据上一阶段的决策和状态来导出本阶段的状态。根据相邻两个阶段状态之间的联系来确定决策方法和状态转移方程。

 

4)寻找边界条件

状态转移方程是一个递推式,因此需要找到递推终止的条件。

 

动态规划算法基本框架

for(j=1; j<=m; j=j+1) // 第一个阶段

   xn[j] = 初始值;

 

for(i=n-1; i>=1; i=i-1)// 其他n-1个阶段

   for(j=1; j>=f(i); j=j+1)//f(i)与i有关的表达式

     xi[j]=j=max(或min){g(xi-1[j1:j2]), ......, g(xi-1[jk:jk+1])};

 

t = g(x1[j1:j2]); // 由子问题的最优解求解整个问题的最优解的方案

 

print(x1[j1]);

 

for(i=2; i<=n-1; i=i+1)

{  

     t = t-xi-1[ji];

 

     for(j=1; j>=f(i); j=j+1)

        if(t=xi[ji])

             break;

}

 

动态规划算法经典例子

斐波那契数列是最经典的动态规划算法应用实例之一,接下来将从斐波那契数列入手,学习下基于动态规划求解问题。

1.问题描述

斐波那契数列又译为费波拿契数、斐波那契数列、费氏数列、黄金分割数列。

用文字来说,就是斐波那契数列由0和1开始,之后的斐波那契数就是由之前的两数相加而得出。

比如:

0,1,1,2,3,5,8,13,21,34,55,89 ...

从中我们可以发现从第三个数开始的值是前两个值的和。

 

2.基本思路

根据斐波那契数列公式,在数列个数大于2的情况下,后一项的值等于前两项的值的和。

也就是说,问题的求解依赖其子问题的求解,显然这个问题可以使用递归算法解决。

但是,也应注意到该递归算法会反复地求解相同的子问题,而不是一直生成新的子问题,而动态规划通过安排问题的求解顺序,确保每个子问题只求解一次。

将结果保存起来,如果随后再次需要此子问题的解,只需查找保存的结果,而不必重新计算,所以,可以使用动态规划求解该问题。

 

3代码示例

public int fibInDynamicProgramming(int n) {
    if (n < 2) {
        return n;
    }
    // 暂存中间结果
    int first = 0;
    int second = 1;
    int result = first + second;
    for (int i = 2; i <= n; i++) {
        result = first + second;
        first = second;
        second = result;
    }
    return result;
}

 

陈睿mikechen

10年+大厂架构经验,资深技术专家,就职于阿里巴巴、淘宝、百度等一线互联网大厂。

关注「mikechen」公众号,获取更多技术干货!

后台回复面试即可获取《史上最全阿里Java面试题总结》,后台回复架构,即可获取《阿里架构师进阶专题全部合集

评论交流
    说说你的看法