【算法】动态规划 ① ( 动态规划简介 | 自底向上的动态规划示例 | 自顶向下的动态规划示例 )

这篇具有很好参考价值的文章主要介绍了【算法】动态规划 ① ( 动态规划简介 | 自底向上的动态规划示例 | 自顶向下的动态规划示例 )。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。





一、动态规划简介



动态规划 , 英文名称 Dynamic Programming , 简称 DP , 不是具体的某种算法 , 是一种算法思想 ;

具体的算法都有具体的步骤 , 如 : 二分法 , 其 有固定的解决步骤 , 先取一个中心点 , 判断解在左边还是右边 , 然后在一边再取一个中心点 , 再进行判定 , 该算法有具体的步骤 ;


动态规划 , 没有具体的步骤 , 只有一个核心思想 ;

动态规划 的 核心思想 是 由大化小 , 大规模问题 使用 小规模问题 计算结果 解决 , 类似于 分治算法 ;


动态规划 与 贪心算法 区别 :

  • 动态规划为了长远利益 损害当前利益 ; 动态规划 不仅仅 考虑下一步的利益 , 还 对 后面十几步甚至几十步进行了大量计算 , 得到了最佳结果 ;
  • 贪心算法 只注重 当前利益最大化 ; 贪心算法 只考虑下一步的最佳利益 ;

动态规划 实现方法 :

  • 递归 : 记忆化搜索 的实现 ;
  • for 循环 : 使用 多重 for 循环 实现 ;




二、自底向上的动态规划示例



从 下图的 数字三角形 中 从上到下 找到一条 最短路径 ;

动态规划自底向上和自顶向下,算法,算法,动态规划,贪心算法,自底向上的动态规划,自顶向下的动态规划


1、原理分析


自底向上 的动态规划思想 : 下面的 n 的最佳路径 指的是 以 n 为起点 到达 最底层的 的最短路径 ;


顶部的 1 的最佳路径 依赖于 2 和 3 中的 最佳路径 , 选择最佳的路径即可 ;

  • 2 的最佳路径 依赖于 4 和 -5 中的最佳路径 ,
    • 4 的最佳路径 依赖于 7 和 8 中的最佳路径 ,
    • -5 的最佳路径 依赖于 8 和 9 中的最佳路径 ,
  • 3 的最佳路径 依赖于 -5 和 6 中的最佳路径 ,
    • -5 的最佳路径 依赖于 8 和 9 中的最佳路径 ,
    • 6 的最佳路径 依赖于 9 和 10 中的最佳路径 ,

最后一排中 ( 第四排 ) :

  • 7 走到最底层的 最小路径 是其本身 7
  • 8 走到最底层的 最小路径 是其本身 8
  • 9 走到最底层的 最小路径 是其本身 9
  • 10 走到最底层的 最小路径 是其本身 10

倒数第二排 ( 第三排 ) :

  • 4 的 最短路径 从 7 和 8 之间取最短的最短路径 , 是 7 , 对应最短路径 7 , 最短路径为 4 + 7 = 11
  • -5 的最短路径 从 8 和 9 之间取最短的最短路径 , 是 8 , 对应最短路径 8 , 最短路径为 -5 + 8 = 3
  • 6 的 最短路径 从 9 和 10 之间取最短的最短路径 , 是 9 , 对应最短路径 9 , 最短路径为 6 + 9 = 15

倒数第三排 ( 第二排 ) :

  • 2 的 最短路径 从 4 和 -5 之间取最短的最短路径 , 是 -5 , 对应最短路径 3 , 最短路径为 2 + 3 = 5
  • 3 的最短路径 从 -5 和 6 之间取最短的最短路径 , 是 -5 , 对应最短路径 3 , 最短路径为 3 + 3 = 6

倒数第四排 ( 第一排 ) :

  • 1 的 最短路径 从 2 和 3 之间取最短的最短路径 , 是 2 , 对应最短路径 5 , 最短路径为 1 + 5 = 6

通过分析 , 可以得出 从 1 开始的最短路径为 1 -> 2 -> -5 -> 8 , 最短路径为 6 ;

动态规划自底向上和自顶向下,算法,算法,动态规划,贪心算法,自底向上的动态规划,自顶向下的动态规划


2、算法设计


将下图的数据 , 存放到 二维数组 triangle 中 , 作为 数据源 使用 ;

该 triangle 二维数组 ,

  • 第 0 行有 1 个数字 ,
  • 第 1 行有 2 个数字 ,
    … ,
  • 第 n-1 行有 n 个数字 ;

该二维数组的长度 , 就是 数字三角形 中的行数 ;

动态规划自底向上和自顶向下,算法,算法,动态规划,贪心算法,自底向上的动态规划,自顶向下的动态规划


状态记录 : 创建 二维数组 dp , dp[i][j] 表示从 第 i 行 第 j 列的元素出发 , 数组的元素值就是走到最底层的最短路径 ;

dp 二维数组 的作用就是用于 记录状态值 , 如 :

  • dp[0][0] 表示从第 0 行第 0 列 的 1 出发 , 走到最底层的最短路径 , 其值为 6 ;
  • dp[3][2] 表示从第 3 行第 2 列 的 -5 出发 , 走到最底层的最短路径 , 其值为 3 ;

dp[0] 只有一个有效元素 , dp[1] 有两个有效元素 , dp[2] 有三个有效元素 , dp[4] 有四个有效元素 ;


初始化数据 : 假设 该 三角形有 n 行数据 ;

那么 , 第 n - 1 行 , 也就是最后一行 , 该 n - 1 行有 n 个数字 , i 取值 0 ~ n - 1 , 则 dp[n-1][i] 的值就是 其本身 triangle[n-1][i]

数字三角形 最后一行 数字 , 即 n -1 行 数字 , 作为 初始化数据 ; 然后开始从 n - 2 行开始计算 ;


运算方程 : 设置具体的算法如何进行计算 , 从 n - 2 行开始计算 本行数据的 最短路径 ;

n - 2 行 的 第 i 个数字 的 最短路径 , 依赖于 n - 1 行 第 i 个数字第 i + 1 个数字最短路径 , 取较小的最短路径 ;


最终结果 : 使用上述 运算方程 从 第 n - 2 行 进行遍历 , 最终计算出 第 0 行 第 0 列 数字元素的最短路径 , 存储在二维数组 dp[0][0] 元素上 ;


上述算法中 二维数组 dp 中 , 每个元素 , 第 dp[i][j] 就是一个 子问题 , 表示 数字三角形中 第 i 行 第 j 列 元素的 最短路径 , 通过这些子问题的解决 , 最终得到一个 大规模问题的 解决方案 ;



3、代码示例


代码示例 :

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class Solution {

    /**
     * 三角形最短路径
     * @param triangle  三角形数据
     * @return
     */
    public int minimumTotal(List<List<Integer>> triangle) {
        int n = triangle.size();

        // 动态规划状态 :
        // dp[i][j] 表示从 第 i 行 第 j 列的元素出发 ,
        // 数组的元素值就是走到最底层的最短路径 ;
        int[][] dp = new int[n][n];


        // 动态规划初始化 :
        // 第 n - 1 行 , 也就是最后一行 , 该 n - 1 行有 n 个数字 , i 取值 0 ~ n - 1 ,
        // 则 dp[n-1][i] 的值就是 其本身 triangle[n-1][i]
        // 数字三角形 最后一行 数字 , 即 n -1 行 数字 , 作为 初始化数据 ;
        // 然后开始从 n - 2 行开始计算 ;
        for (int i = 1; i < n; i++) {
            dp[n - 1][i] = triangle.get(n - 1).get(i);
        }

        // 动态规划方程 :
        // n - 2 行 的 第 i 个数字 的 最短路径 ,
        // 依赖于 n - 1 行 的 第 i 个数字 和 第 i + 1 个数字 的 最短路径 ,
        // 取较小的最短路径 ;
        for (int i = n - 2; i > -1; i--) {
            for (int j = 0; j < i + 1; j++) {
                dp[i][j] = Math.min(dp[i + 1][j], dp[i + 1][j + 1]) // 先取一个最短路径最小值
                        + triangle.get(i).get(j);   // 再加上改点计算出一个新的最短路径
            }
        }

        // 动态规划结果 :
        // 使用上述 运算方程 从 第 n - 2 行 进行遍历 ,
        // 最终计算出 第 0 行 第 0 列 数字元素的最短路径 ,
        // 存储在二维数组 dp[0][0] 元素上 ;
        return dp[0][0];
    }


    public static void main(String[] args) {
        List<List<Integer>> triangle = new ArrayList<List<Integer>>(){
            {
                add(new ArrayList<Integer>(Arrays.asList(1)));
                add(new ArrayList<Integer>(Arrays.asList(2, 3)));
                add(new ArrayList<Integer>(Arrays.asList(4, -5, 6)));
                add(new ArrayList<Integer>(Arrays.asList(7, 8, 9, 10)));
            }
        };

        int minTotal = new Solution().minimumTotal(triangle);
        System.out.println("三角形最短路径为 " + minTotal);
    }
}

执行结果 :

三角形最短路径为 6

动态规划自底向上和自顶向下,算法,算法,动态规划,贪心算法,自底向上的动态规划,自顶向下的动态规划





三、自顶向下的动态规划示例



从 下图的 数字三角形 中 从上到下 找到一条 最短路径 ;

动态规划自底向上和自顶向下,算法,算法,动态规划,贪心算法,自底向上的动态规划,自顶向下的动态规划


每个点 都有 从起点开始 走到该点 的 最短路径 ;

  • 4 这个点 , 从 起点 1 开始走 , 肯定走 1 -> 2 -> 4 路线 是最短路径 , 为 7 ;
  • -5 这个点 , 从 起点 1 开始走 , 肯定走 1 -> 2 -> -5 路线 是最短路径 , 为 -2 ;


1、算法设计


状态记录 : 创建 二维数组 dp , dp[i][j] 表示从 起点 走到 第 i 行 第 j 列的元素的最短路径 , 数组的元素值就是走到最底层的最短路径 ;

dp 二维数组 的作用就是用于 记录状态值 , 如 :

  • dp[0][0] 表示 从起点 第 0 行第 0 列 的 1 出发 , 走到当前点 第 0 行第 0 列 的 1 的最短路径 , 其值为 1 ;
  • dp[3][2] 表示 从起点 第 0 行第 0 列 的 1 出发 , 走到当前点 第 3 行第 2 列 的 -5 的最短路径 , 其值为 -2 ;

dp[0] 只有一个有效元素 , dp[1] 有两个有效元素 , dp[2] 有三个有效元素 , dp[4] 有四个有效元素 ;


初始化数据 : 没有办法套入 动态规划方程 中的点 进行初始化操作 ;

在套用下面的 运算方程时 , 会发现 , 最左侧的一排数字 , 没有左上角的元素 , 也就是 第 i 行 第 j 列 的数字 其左上角的数字是 第 i - 1 行 第 j - 1 列 , 如果 j = 0 , 那么左上角 j - 1 肯定为负数 ; 因此 最左侧一列 和 最右侧一列 是无法在 运算方程中直接计算的 ;

此处初始化 顶点 的最短路径 , 和 最左侧一列 和 最右侧一列 数字 的最短路径 ;


运算方程 : 设置具体的算法如何进行计算 , 从 n - 2 行开始计算 本行数据的 最短路径 ;

第 i 行 第 j 列 的数字 , 从顶点走到该点的最短路径 , 依赖于 左上角 第 i - 1 行 第 j - 1 列 的 数字 的最短路径 , 和 右上角 的 第 i - 1 行 第 j 列 的 数字 的 最短路径 , 找出 上面 二者 最短路径较小 的最短路径 作为结果 ;


最终结果 : 在进行最后一层 计算时 , 会得到 第 n - 1 层 , 也就是最后一层 , 所有元素的最短路径 , 选择 最小的 最短路径 , 就是本次的最短路径 ;


上述算法中 二维数组 dp 中 , 每个元素 , 第 dp[i][j] 就是一个 子问题 , 表示 数字三角形中 从起点开始 第 i 行 第 j 列 元素的 最短路径 , 通过这些子问题的解决 , 最终得到一个 大规模问题的 解决方案 ;



2、代码示例


代码示例 :

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class Solution {

    /**
     * 三角形最短路径
     * @param triangle  三角形数据
     * @return
     */
    public int minimumTotal(List<List<Integer>> triangle) {
        int n = triangle.size();

        // 动态规划状态 :
        // dp[i][j] 表示从 起点 走到 第 i 行 第 j 列的元素的最短路径 ,
        // 数组的元素值就是走到最底层的最短路径 ;
        int[][] dp = new int[n][n];


        // 动态规划初始化 : 没有办法套入 动态规划方程 中的点 进行初始化操作
        // 起始点的最短路径是其本身
        dp[0][0] = triangle.get(0).get(0);
        // 遍历 1 ~ n 行
        for (int i = 1; i < n; i++) {
            // 每行第 0 个元素的 最短路径 , 该元素没有左上角的点
            dp[i][0] = dp[i - 1][0] + triangle.get(i).get(0);
            // 每行第 n - 1 个元素的 最短路径 , 该元素没有右上角的点
            dp[i][i] = dp[i - 1][i - 1] + triangle.get(i).get(i);
        }

        // 动态规划方程 :
        // 第 i 行 第 j 列 的数字 , 走到该点的最短路径 ,
        // 依赖于 左上角 第 i - 1 行 第 j - 1 列 的 数字 的最短路径 ,
        // 和 正上方的 第 i - 1 行 第 j 列 的 数字 的 最短路径 ,
        // 找出 上面 二者 最短路径较小 的最短路径 作为结果 ;
        // 此处从 i = 2 开始 , 是因为 第一排的两个数字的最短路径已经初始化过了 , 在初始化中已经进行了初始化
        for (int i = 2; i < n; i++) {
            // j 的取值只能是 1 ~ i - 1 , 将每一行的 第 0 个 和 第 i 个 元素剔除出去
            for (int j = 1; j < i; j++) {
                dp[i][j] = Math.min(dp[i - 1][j - 1], dp[i - 1][j]) + triangle.get(i).get(j);
            }
        }

        // 动态规划结果 :
        // 在进行最后一层 计算时 , 会得到 第 n - 1 层 , 也就是最后一层 , 所有元素的最短路径 ,
        // 选择 最小的 最短路径 , 就是本次的最短路径 ;
        int minTotal = dp[n - 1][0];
        for (int i = 1; i < n; ++i) {
            minTotal = Math.min(minTotal, dp[n - 1][i]);
        }
        return minTotal;
    }


    public static void main(String[] args) {
        List<List<Integer>> triangle = new ArrayList<List<Integer>>(){
            {
                add(new ArrayList<Integer>(Arrays.asList(1)));
                add(new ArrayList<Integer>(Arrays.asList(2, 3)));
                add(new ArrayList<Integer>(Arrays.asList(4, -5, 6)));
                add(new ArrayList<Integer>(Arrays.asList(7, 8, 9, 10)));
            }
        };

        int minTotal = new Solution().minimumTotal(triangle);
        System.out.println("三角形最短路径为 " + minTotal);
    }
}

执行结果 :

三角形最短路径为 6

动态规划自底向上和自顶向下,算法,算法,动态规划,贪心算法,自底向上的动态规划,自顶向下的动态规划文章来源地址https://www.toymoban.com/news/detail-795540.html

到了这里,关于【算法】动态规划 ① ( 动态规划简介 | 自底向上的动态规划示例 | 自顶向下的动态规划示例 )的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Java中常用算法及示例-分治、迭代、递归、递推、动态规划、回溯、穷举、贪心

    1、分治算法的基本思想是将一个计算复杂的问题分成规模较小、计算简单的小问题求解, 然后综合各个小问题,得到最终答案。 2、穷举(又称枚举)算法的基本思想是从所有可能的情况中搜索正确的答案。 3、迭代法(Iterative Method) 无法使用公式一次求解,而需要使用重复结构

    2024年02月08日
    浏览(45)
  • 2023-05-02 动态规划简介

    阶段、状态、决策、策略、状态转移方程 1) 阶段和阶段变量 将问题的全过程恰当地分成若干个相互联系的阶段 闫氏DP分析法:对应f[i][j]的ij遍历时形成的所有f[i][j] 阶段的划分一般根据时间和空间的自然特征去划分 阶段的划分便于把问题转化成 多阶段决策 问题 2) 状态和状

    2024年02月03日
    浏览(35)
  • 【算法】动态规划 ⑧ ( 动态规划特点 )

    求解类型 : 动态规划 必须是求 最值 , 可行性 , 方案数 , 三者之一 , 如果求其它内容 , 则不能使用动态规划算法 ; 求最值 : 最大值 , 最小值 等 ; 大规模问题的结果 由 小规模问题 的计算结果 取最大值 大规模问题的结果 由 小规模问题 的计算结果 取最小值 可行性 : 是否可行

    2023年04月08日
    浏览(48)
  • 【算法 - 动态规划】原来写出动态规划如此简单!

    从本篇开始,我们就正式开始进入 动态规划 系列文章的学习。 本文先来练习两道通过 建立缓存表 优化解题过程的题目,对如何将 递归函数 修改成 动态规划 的流程有个基本的熟悉。 用最简单的想法完成题目要求的 递归 函数; 定义明确 递归函数 的功能!!! 分析是否存

    2024年02月21日
    浏览(48)
  • 基于PCL的RANSAC(随机采样一致)算法简介与示例

    RANSAC(Random sample consensus,随机采样一致)是3D点云拟合的一种重要的手段,可以对直线、圆、平面,圆球、圆柱等形状的点云进行拟合,其优点在于可以最大程度上减少噪声点对拟合效果的影响。 RANSAC各种类型拟合的计算原理基本类似。 1,进行随机抽样,如直线,就随机找

    2024年02月02日
    浏览(49)
  • 60题学会动态规划系列:动态规划算法第三讲

    简单多状态问题 文章目录 一.按摩师 二.打家劫舍系列 三.删除并获得点数 四.粉刷房子 力扣链接:力扣 一个有名的按摩师会收到源源不断的预约请求,每个预约都可以选择接或不接。在每次预约服务之间要有休息时间,因此她不能接受相邻的预约。给定一个预约请求序列,

    2024年02月08日
    浏览(49)
  • 60题学会动态规划系列:动态规划算法第四讲

    买卖股票相关的动态规划题目 文章目录 1. 买卖股票的最佳时机含冷冻期 2. 买卖股票的最佳时期含⼿续费 3. 买卖股票的最佳时机III 4. 买卖股票的最佳时机IV 力扣链接:力扣 给定一个整数数组 prices ,其中第    prices[i]  表示第  i  天的股票价格 。​ 设计一个算法计算出最

    2024年02月13日
    浏览(36)
  • 60题学会动态规划系列:动态规划算法第五讲

    子数组系列题目 文章目录 1.最大子数组和 2.环形子数组的最大和 3.乘积最大数组 4.乘积为正数的最长子数组长度 5.等差数列划分 6.最长湍流子数组 7.单词拆分 8.环绕字符串中唯一的子字符串 力扣链接:力扣 给你一个整数数组  nums  ,请你找出一个具有最大和的连续子数组(

    2024年02月15日
    浏览(69)
  • 60题学会动态规划系列:动态规划算法第一讲

    坚持就是胜利 - -  文章目录 1.第N个泰波那切数 2.三步问题 3.使用最小花费爬楼梯 4.解码方法 力扣链接:力扣 泰波那契序列 Tn 定义如下:  T0 = 0, T1 = 1, T2 = 1, 且在 n = 0 的条件下 Tn+3 = Tn + Tn+1 + Tn+2 给你整数  n ,请返回第 n 个泰波那契数 Tn 的值。  首先我们分析一下

    2024年02月06日
    浏览(45)
  • 60题学会动态规划系列:动态规划算法第二讲

    都是路径问题~ 文章目录 1.不同路径 2.不同路径II 3.礼物的最大价值 4.下降路径最小和 5.最小路径和 力扣链接:力扣 一个机器人位于一个  m x n   网格的左上角 (起始点在下图中标记为 “Start” )。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在

    2024年02月07日
    浏览(59)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包