程序员算法基础——动态规划

作者: 落影loyinglin | 来源:发表于2018-05-13 00:17 被阅读945次

    前言

    本文以一道BAT常见的算法面试题开篇,引入动态规划的基础概念, 介绍其思考过程。

    正文

    一、BAT最常见的一道算法面试题——上台阶

    有一个楼梯总共n个台阶,只能往上走,每次只能上1个、2个台阶,总共有多少种走法。

    解决方案:
    1、排列组合;
    枚举2的个数,再枚举2具体放的位置;
    计算复杂,容易遗漏。

    2、动态规划;
    dp[n] 表示n个台阶的走法,那么有:
    dp[n]=dp[n-1]+dp[n-2];
    思路清晰,代码简单。

    二、动态规划基础概念

    1、动态规划;
    动态规划(Dynamic Programming)指的是解最优化问题的一种方法。

    2、最优子结构性质;
    问题的最优解可以分解为若干子问题,且子问题的解也是最优的;
    以上台阶为例,到第i层的最多走法,可以分解为第i-1层和第i-2层的走法之和,且第i-1层和第i-2层的走法也是最多的;

    3、 无后效性;
    现阶段的决策不会影响未来的决策;
    以上台阶为例,走到第i-2层的最多走法,不会因为增加第i-1层而改变;

    三、动态规划思考过程

    动态规划的思考过程可以总结为:大事化小,小事化了。
    大事化小:
    一个较大的问题,通过找到与子问题的重叠,把复杂的问题划分为多个小问题,也称为状态转移;
    小事化了:
    小问题的解决通常是通过初始化,直接计算结果得到;

    具体的步骤

    • 1、将大问题分解为子问题
    • 2、确定状态表示
    • 3、确定状态转移
    • 4、考虑初始状态和边界情况

    四、另一个经典的例子——数塔

    有如图所示的数塔,要求从顶层走到底层,若每一步只能走到相邻的结点,则经过的结点的数字之和最大是多少?

    题目链接点这里


    解决思路:
    1、大事化小。要到达第i层,先要到达第i-1层。并且第i层的第j个节点,只能由i-1层的第j个和第j-1个节点到达。
    我们用dp[i][j]表示,走到第i层第j个位置的数字最大和。
    那么有dp[i][j]=max(dp[i-1][j], dp[i-1][j-1]) + a[i][j];

    2、小事化了。第1层的第1个节点,初始值为dp[1][1]=a[1][1]。(a[x][y]表示第x层,第y个的值)

    五、数塔例子的变形——收集苹果

    平面上有N*M个格子,每个格子中放着一定数量的苹果。
    你从左上角的格子开始,每一步只能向下走或是向右走,每次走到一个格子上就把格子里的苹果收集起来。
    这样下去,你最多能收集到多少个苹果。

    解决思路:
    1、只能向右走或者向下走,要到达第i行第j列的格子的时候,可以由第i-1行第j列或者第i行第j-1列到达,我们用dp[i][j]表示,走到第i行第j列的最多苹果数,那么有:
    dp[i][j]=max(dp[i-1][j], dp[i][j-1]) + a[i][j];

    2、第1行第1列,初始值为dp[1][1]=a[1][1],注意事项是边界条件的处理。

    六、动态规划经典——01背包问题

    给定n件物品和一个容量为m的背包,每件物品都会消耗背包的一定容积c[i],并带来一定价值v[i],要求如何选取装入背包中的物品,使得背包内的物品价值最大。

    解决思路:
    把n件物品放入背包,可以分解为“将前i件物品放入容量为m的背包中”问题。
    若只考虑第i件物品的选择,那么问题可以分为两种情况:
    1、如果不放第i件物品,问题就转化为“前i-1件物品放入容量为v的背包中”
    2、如果放第i件物品,问题就转化为“前i-1件物品放入剩下的容量为m-c[i]的背包中”

    我们用f[i][j]表示前i个物品,放入容量为j的背包的最大价值,上面的两种情况可以表示为
    f[i][j] = max(f[i-1][j], f[i-1][j-c[i]]+v[i]);

    初始化条件memset(dp, 0, sizeof(dp));dp[1][c[1]]=v[1]
    最后遍历f[n][1~m]可以得到最大值。

    总结

    如果还不能完全理解01背包,那么还需要再仔细理解最优子结构状态表示状态转移
    算法能扩展思考方向,完善思维能力。学会“上台阶”、“数塔”、“01背包”这三个题目,能解决算法面试的动态规划部分。

    相关文章

      网友评论

      • 一条特立独行的咸鱼:数塔的那个,a[1][1]取哪个
      • artzok:大学时做数学竞赛经常用Lingo编程解决线性规划和动态规划,隐约记得使用lingo创建动态规划模型会简单很多,至少很好理解,不知道楼主是否了解,能否开篇讲讲:smile:
      • helloKimmy:介绍的是用递归法解动态规划问题,这是一种很基础、很扎实的解题思路,实际上就是倒推法最基本的一种想法。但是,路由变长后,由于节点变多、积和变大,算法可能无法实现。所以,动态规划问题一直存在赌博策略和决策风险管理这一分枝。:smile::smile::smile:
        落影loyinglin:@helloKimmy :+1:🏻
      • 知识学者:动态规划是不好玩的 ....
        落影loyinglin:这个很优雅,每次解决一个题目会有一种畅快淋漓的感觉。
      • 829ef3703051:有算法详细的资料,视频没?
        829ef3703051:@李小逗_0921 有的数学书搞不懂,推荐一下呗😜😜
        落影loyinglin:@北城的天 详细资料的话 有大学教材 也有刘汝佳的书
        9916b4959de4:@北城的天 数学书应该能够满足你了🤔

      本文标题:程序员算法基础——动态规划

      本文链接:https://www.haomeiwen.com/subject/asdgrftx.html