动态规划法的教学引例——数字三角形问题

动态规划法的教学引例——数字三角形问题
作者:张惠艳 陈芳
来源:《电脑知识与技术》2022年第24期
        摘要:针对数字三角形问题,设计了深度优先搜索算法,记忆化搜索算法,动态规划法的不同解决方案。文章从算法思想、算法实现以及算法复杂度三个部分对该问题的教学方法进行了探讨,便于学生理解和掌握递归和动态规划法的设计思想。
        关键词:数字三角形;深度优先搜索算法;记忆化搜索算法;动态规划法
        中图分类号:G642 文献标识码:A
        文章编号:1009-3044(2022)24-0069-03
        1 引言
        动态规划[1](Dynamic Programming 简称DP) 是解决“多阶段决策问题”的一种高效算法。通过合理组合子问题的解从而解决整个问题解的一种算法。其中子问题并不是独立的,这些子问题又包含有公共的子子问题。动态规划算法就是对每个子问题只求一次,并将其结果保存在一张表中(数组),以后再用到时直接从表中拿过来使用,避免重复计算相同的子问题。“不做无用功”的求解模式,大大提高了程序的效率。动态规划算法常用于解决统计类问题(统计方案总数) 和最优值问题(最大值或最小值) ,尤其普遍用于最优化问题。动态规划算法能解决的问题主要分为线性型(如最长公共子序列) ,坐标型(如多段图问题,数字三角形) ,区间型(如矩阵连乘) ,背包型(如0-1背包问题) ,树型(如选课问题) 等。传统讲解方法都是直接用经典例题背包问题[2],不便于初学者理解重复子问题的产生、解决方法,以及动态规划法的设计策略。毛发生长剂
        数字三角形问题曾是国际信息学(计算机)奥林匹克竞赛的试题,这一问题可采用深度优先搜索算法,记忆化搜索算法,以及动态规划法的方法来设计解决,可作为算法设计与分析课程中动态规划法这一章内容的引例纳入课程中讲解。通过该例的三种不同算法设计的讲解以及路径的追踪可以让学生深刻体会深度优先搜索算法递归解决该问题存在重复的子问题,大大降低了算法的效率;为了解决重复的子问题,提出了记忆化搜索算法,减少重复的子问题的求解,提高算法效率;进一步分析发现数字三角形问题有明显的阶段性,可用表记录子问题的解,以后可以直接使用,非常自然地过渡到动态规划的讲解,提出动态规划法的备忘录和路径追踪。所以此问题非常适合动态规划法教学的引例,便于学生理解该法的设计思想和适用问题,为动态规划法的教学做铺垫。采用典型实例教学[3],将复杂抽象算法理论与简单的典型实例有机结合,这样使学生由被动学习变为主动学习,培养学生对算法学习的兴趣。同一问题的不同算法实现,对于提升学生的逻辑思维能力和编程解决实际问题的能力也有着非常重要的意义[4-5],能为学生进一步分析和解决计算机科学与技术领域的复杂工程问题奠定良好基础。
        2 问题描述
        有一个数字三角形,从最顶层出发,每一步只能向左下或右下方向走。编程求从最顶层到最底层的一条路所经过位置上的数字之和的最大值。输入样例如图1、图2所示,为方便讲解,用图2向正下或右下方向走。输出:一个正整数,路径上数字之和的最大值。
        3 算法设计
        3.1 深度优先搜索算法
        深度优先搜索(缩写DFS) 是对一个连通图进行遍历的算法。它的思想是从一个顶点V0开始,沿着一条路一直走到底,这种尽量往深处走的概念即是深度优先的概念。从数字三角形的第一个顶点向左下或右下方向一直走到最后一行的结点的过程就是深度优先搜索,图1、图2的图形可以理解为只是形状不同,都可以采用二维数组a[Max][Max]存储,Max是数字三角形的行数,可在程序的开头用const int进行定义。当前结点的坐标记为(i,j),左下方结点的坐标可以标记为(i+1,j),右下方结点的坐标可以标记为(i+1,j+1)。数字三角形问题的深度优先搜索算法的C++代码可写为:
        int DigitalTriangle_Recursion(int i, int j)
        { if (i==Max-1) return a[i][j];
机房环控
        int left=DigitalTriangle_Recursion(i+1,j);
        int right=DigitalTriangle_Recursion(i+1,j+1);
        int curMAX=left>right?left:right;
        return curMAX+a[i][j];
        }
        深度優先搜索算法必然要递归实现,通过递归调用分析可知,若是10行的数字三角形,如图3,每个子问题被递归调用的次数如图4,10行数字三角形中子问题调用最多的次数将达126次,这种算法设计方法大大降低了求解问题的效率,需要改进算法,提高效率。
        3.2 记忆化搜索算法
        记忆化搜索是在递归的过程中,将已经计算出来的结果保存起来,之后再次用到时直接取出结果,避免重复运算,可提高算法的效率。用二维数组a记录数字三角形,二维数组f保存数字三角形中已经计算出来的结点值,记忆化搜索算法的C++代码为:
        int f[Max][Max] = { -1 };
        int DigitalTriangle_Memory(int i, int j)
高压脉冲电容器        {
        if (temp[i][j]) return f[i][j];
        if (i == Max-1) return (f[i][j] =a[i][j]);
        int left = DigitalTriangle_Memory(i + 1, j);
大蒜剥皮机        int right = DigitalTriangle_Memory(i + 1, j + 1);
        int curMAX = left > right ? left : right;
        return (f[i][j] = curMAX +a[i][j]);
        }
        数组f的元素初始化-1,数组大小等同于数组a。记忆化搜索算法可使数字三角形每个子问题仅被计算一次,大大提高了算法的效率。若是10行的数字三角形,如图3,每个子问题被递归调用的次数如图5,10行数字三角形中每个子问题最多被调用一次,所以算法的时间复杂度为Ο(n2)。
        因为存储每一次计算的结果,需要一个跟原数字三角形一样大小的二维数组,牺牲了空间。既然已经牺牲了空间,能否进一步提高效率,消除递归?动态规划法可消除递归,而且可追踪出得到最大值的路径,如图1的最大值为30,路径:7->3->8->7->5。
        3.3 动态规划法
        数字三角形的递归求解存在重复的子问题,用表记录子问题的解,以后可以直接使用。在求解最值的过程中,将三角形的每一行看成一个阶段,因此有明显的阶段性,这是典型的坐标型问题,可采用动态规划算法求解。对坐标型问题动态规划法通常都有正推和
倒推两种实现方法。
        正推:从a[0][0]出发,按照向下或右下方向一直走到最后一行,依次计算f[i][j]的值,递推方程:f[i,j]=max(f[i-1,j-1],f[i-1,j])+a[i,j],因为第一列从第二个元素开始只能用其正上方的元素求得,从第二行开始的对角线的元素只能由其斜上方的元素求得,因此递推方程不适用边界值,边界值要单独处理。问题的解需在二维数组f的最后一行中求最大值,其C++实现代码如下:
        int DigitalTriangle_DP() {
        int f[Max][Max];5b5b5b5b
        f[0][0]=a[0][0];
        for (int i= 1;i< Max; ++i) //边界值处理
        {f[i][0]=f[i-1][0]+a[i][0];
        f[i][i]=f[i-1][i-1]+a[i][i];
        }
        for(int i=2;i<Max;i++)
        for (int j = 1; j <i; j++)
        {f[i][j]=max(f[i-1][j],f[i-1][j-1])+a[i][j];
清洗空调现摄像头
        }
        int ans=f[Max-1][0];
        for(int j=1;j<=Max-1;j++)
        if(f[Max-1][j]>ans) ans=f[Max-1][j];
        return ans;;
        }
        倒推:从数组a的最后一行出发,将最后一行先赋给数组f的对应元素,按照向上或左上方向一直倒推到第一行,依次计算f[i][j]的值,递推方程:f[i,j]=max(f[i+1,j],f[i+1,j+1])+a[i,j],f[0][0]即是问题的解,其C++代码如下:

本文发布于:2024-09-23 05:32:11,感谢您对本站的认可!

本文链接:https://www.17tex.com/tex/2/191750.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2024 Comsenz Inc.Powered by © 易纺专利技术学习网 豫ICP备2022007602号 豫公网安备41160202000603 站长QQ:729038198 关于我们 投诉建议