动态规划(DP)及相关经典问题讲解

前言

动态规划(DP)是计算机编程算法中非常重要的一个知识点,无论是校招 社招,面试官也经常喜欢出此类的编程题来考察面试者的编程能力, 这篇博客主要是概述一下dp的主要思想 然后重点归纳一下动态规划相关经典问题的讲解。

DP基础知识

DP简单可以总结为“一个模型三个特征”。

  • “一个模型”是指动态规划适合解决的问题的模型,也就是多阶段决策最优解模型(这个模型同时也是回溯 贪心解决问题的模型)。一般用动态规划解决最优问题时,解决问题需要经历多个决策阶段。每个决策阶段都对应着一组状态。然后我们寻找一组决策序列,经过这组决策序列,能够产生最后在那个期望求解的最优值。
  • “三个特征”指的是:最优子结构、无后效性和重复子问题。
    在这里插入图片描述
    牢记,dp问题最重要的核心写出状态转移方程
    状态转移方程法的思路:找最优子结构——写状态转移方程——将状态转移方程翻译成代码

上面的知识归纳 读者可以看看后 留个印象,下面我们来看看具体的习题。

经典习题

杨辉三角的最短路径问题

求解 从第一层走到最后一层的最短路径长度是多少
在这里插入图片描述
如上面左图所示,也就是我们常见的杨辉三角结构, 在计算机的存储表示中 他的形式如同上面右图所示。每一个节点的运动方向在图中显示, 根据节点数值的运动方向,我们可以比较清晰的概括出该问题的dp状态转换方程dp[i][j]。

代码如下:

		public int shortestPath(int[][] array) {
   
            //首先定义一个二维的状态转换数组 中间的值存储的是当前走过的路径
            int[][] dp = new int[array.length][array[array.length - 1].length];
            dp[0][0] = array[0][0];
            //DP的过程如下: 画图便能得到
            // 第一列元素对应的状态值只会是运动方向向下得到的 states[i][0]=states[i-1][0]+tri[i][0]
            //中间位置的states[i][j] 可以由[i-1][j-1]和[i-1][j]较小的值得到
            // 每一行的最后一个元素[i][j]由[i-1][j-1]得到
            for (int i = 1; i < array.length; i++) {
   
                for (int j = 0; j < array[i].length; j++) {
   
                    if (j == 0) dp[i][j] = dp[i - 1][j] + array[i][j];
                    else if (j == array[i].length - 1) dp[i][j] = dp[i - 1][j - 1] + array[i][j];
                    else dp[i][j] = Math.min(dp[i - 1][j - 1], dp[i - 1][j]) + array[i][j];
                }
            }

            //输出最小值 也就是二维数组中最后一行中的最小值
            int min = Integer.MAX_VALUE;
            for (int j = 0; j < dp[array.length - 1].length; j++) {
   
                min = Math.min(min, dp[array.length - 1][j]);
            }
            return min;
        }

左上到右下的最短路径

一个二维数组中,每个节点的运动方向只能是向下或者向右。求解从左上到右下的最短路径:
在这里插入图片描述
因为和上一题杨辉三角的最短路径相似,这里不再进行过多赘述。 dp状态转换方程如图所示。

		public int shortestPath(int[][] a) {
   
            int n = a.length, m = a[0].length;
            int[][] states = new int[n][m];   定义状态转换数组
            //开始写DP过程
            //大多数位置的值states[i][j] 由min(states[i-1][j],states[i][j-1])得到
            //第一行只能往右移动 第一列只能向下移动
            states[0][0] = a[0][0];
            for (int i = 1; i < m; i++) {
   
                states[0][i] = states[0][i - 1] + a[0][i];    //第一行
            }
            for (int i = 1
  • 4
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值