点击上方“小白学视觉”,选择加"星标"或“置顶

重磅干货,第一时间送达

来自 | medium

作者 | Meet Zaveri

乔治·桑塔亚纳说过,“那些遗忘过去的人注定要重蹈覆辙。”这句话放在问题求解过程中也同样适用。不懂动态规划的人会在解决过的问题上再次浪费时间,懂的人则会事半功倍。那么什么是动态规划?这种算法有何神奇之处?本文作者给出了初步的解答。

假设你正在使用适当的输入数据进行一些计算。你在每个实例中都进行了一些计算,以便得到一些结果。当你提供相同的输入时,你不知道会有相同的输出。这就像你在重新计算之前已经计算好的特定结果一样。

那么问题出在哪里呢?你之前计算某些结果的宝贵时间被浪费掉了。你可以通过保存之前的计算结果去轻易地解决这个问题。比如通过使用恰当的数据结构。举个例子,你可以将输入输出作为键值对映射保存起来。

那些遗忘过去的人注定要重蹈覆辙 ~ 动态规划

现在通过分析这个问题,我们可以将新的输入(或者不在数据结构中的输入)与其对应的输出存储下来。或者在字典中查找输入并返回相应的输出结果。这样当你在进行一些计算时,你可以检查数据结构中是否存在该输入,如果数据输入存在的话就可以直接获得结果。我们将与这种方法相关的技巧称作动态规划。

详解动态规划

现在让我们更详细地介绍动态规划。

简而言之,我们可以说动态规划主要用来解决一些希望找到问题最优解的优化问题。

一种可以用动态规划解决的情况就是会有反复出现的子问题,然后这些子问题还会包含更小的子问题。相比于不断尝试去解决这些反复出现的子问题,动态规划会尝试一次解决更小的子问题。之后我们可以将结果输出记录在表格中,我们在之后的计算中可以把这些记录作为问题的原始解。

举个例子,斐波那契数列 0,1,1,2,3,5,8,13,…有着一个相当简单的描述方式,它的每个数字都与前两个紧邻的数字相关。如果 F(n) 是第 n 个数字,那么我们会有 F(n) = F(n-1) + F(n-2)。这个在数学上称作*递归方程*或者*递推关系*。为了计算后面的项,它需要前面项的计算结果作为输入。

大多数动态规划问题都能被归类成两种类型:

  • 优化问题

  • 组合问题

优化问题希望你选择一个可行的解决方案,以便最小化或最大化所需函数的值。组合问题希望你弄清楚做某事方案的数量或某些事件发生的概率。

解决方案的对比:自上而下或者自下而上

以下是两种不同的动态规划解决方案:

  • 自上而下:你从最顶端开始不断地分解问题,直到你看到问题已经分解到最小并已得到解决,之后只用返回保存的答案即可。这叫做记忆存储(*Memoization*)。

  • 自下而上:你可以直接开始解决较小的子问题,从而获得最好的解决方案。在此过程中,你需要保证在解决问题之前先解决子问题。这可以称为表格填充算法(*Tabulation,*table-filling algorithm**)。

至于迭代和递归与这两种方法的关系,自下而上用到了迭代技术,而自上而下则用到了递归技术。

图片中的展示在理论上可能并不完全正确,但这是一种可以理解的展示方式。

这儿有一个普通方法和动态规划方法的比较,你可以看到两者时间复杂度的不同。

Memoization 的准则:不要忘记

Jeff Erickson 在他的笔记中这样描述斐波那契数列:

递归算法之所以速度慢,是因为它一遍又一遍地计算了相同的斐波那契数列。

来自 Jeff Erickson 笔记:http://jeffe.cs.illinois.edu/

我们可以通过记录递归调用的结果来加速递归算法,这样在之后需要这些结果时就不必重新计算了。

Memoization 是指缓存和重用之前计算结果的技术。

如果你使用 Memoization 来解决问题,可以通过维护已经解决的子问题的映射来实现(正如我们之前讨论的键值对映射)。你首先解决「上层」问题(通常是为了解决子问题而进行递归),这样做是「自上而下」。

*memoization*的伪代码

因此在使用递归的过程中,我们使用额外的内存(即这里的 lookup)来执行操作以存储结果。如果查找命中存储值,我们将直接返回它,或者将其添加到特定索引。

请记住,额外的内存与表格填充之间存在一个权衡。

自上而下的方法

Tabulation:以表格形式填充

但是一旦我们看到数组(存储的解决方案)是如何被填充的,我们就可以用一个简单的循环替换递归,这个循环有意地按顺序填充数组,而不是依赖于复杂的递归来为我们完成。

来自 Jeff Erickson 的笔记:http://jeffe.cs.illinois.edu/

Tabulation 以「*自下而上*」的方式进行。它更直接,会计算所有值,但需要的开销更少,因为它不必维护映射并以表格形式为每个值存储数据。它还可以计算不必要的值。如果你只想计算问题的所有值,则可以使用此方法。

*tabulation*的伪代码:

斐波那契树的伪代码

正如您可以在图片中看到的伪代码(右侧),它会进行迭代(即循环直到数组结束)。它从 fib(0),fib(1),fib(2),…开始,所以使用 tabulation 方法,我们可以消除递归,只需通过循环元素返回结果。

追根溯源

Richard bellman 是这个概念的提出者。他在 20 世纪 50 年代中期为兰德公司工作时想到了这一点。选择「dynamic programming」这个名字的原因是为了隐藏他为这项研究所做的数学工作。因为他担心他的老板会反对或不喜欢任何类型的数学研究。

所以「programming」这个词只是一个参考,以表明这是一种老式的计划或调度方式,通常是通过逐渐填充表格(以动态方式而不是线性方式)而不是一次全部填入的方式进行。

下载1:OpenCV-Contrib扩展模块中文版教程

在「小白学视觉」公众号后台回复:扩展模块中文教程即可下载全网第一份OpenCV扩展模块教程中文版,涵盖扩展模块安装、SFM算法、立体视觉、目标跟踪、生物视觉、超分辨率处理等二十多章内容。

下载2:Python视觉实战项目52讲

在「小白学视觉」公众号后台回复:Python视觉实战项目即可下载包括图像分割、口罩检测、车道线检测、车辆计数、添加眼线、车牌识别、字符识别、情绪检测、文本内容提取、面部识别等31个视觉实战项目,助力快速学校计算机视觉。

下载3:OpenCV实战项目20讲

在「小白学视觉」公众号后台回复:OpenCV实战项目20讲即可下载含有20个基于OpenCV实现20个实战项目,实现OpenCV学习进阶。

交流群

欢迎加入公众号读者群一起和同行交流,目前有SLAM、三维视觉、传感器、自动驾驶、计算摄影、检测、分割、识别、医学影像、GAN、算法竞赛等微信群(以后会逐渐细分),请扫描下面微信号加群,备注:”昵称+学校/公司+研究方向“,例如:”张三 + 上海交大 + 视觉SLAM“。请按照格式备注,否则不予通过。添加成功后会根据研究方向邀请进入相关微信群。请勿在群内发送广告,否则会请出群,谢谢理解~

拒绝遗忘:高效的动态规划算法相关推荐

  1. NOIP竞赛学习整理--动态规划算法举例P1264

    动态规划 什么是动态规划? 动态规划是解决多阶段决策最优化问题的一种思想方法.所谓"动态",指的是在问题的多阶段决策中,按某一顺序,根据每一步所选决策的不同,将随即引起状态的转移, ...

  2. 贪心算法,递归算法,动态规划算法比较与总结

    一般实际生活中我们遇到的算法分为四类: 一>判定性问题        二>最优化问题        三>构造性问题        四>计算性问题 而今天所要总结的算法就是着重解 ...

  3. 动态规划 --- 算法思想介绍

    一.动态规划的基本概念 动态规划在五种算法设计方法中难度最大,它建立在最优原则的基础上.采用动态规划方法,可以高效地解决许多用贪婪算法或分治法无法解决的问题.动态规划(dynamic programm ...

  4. 动手学强化学习(三):动态规划算法 (Dynamic Programming)

    动手学强化学习(三):动态规划算法 (Dynamic Programming) 1. 简介 2. 悬崖漫步环境 3. 策略迭代算法 3.1 策略评估 3.2 策略提升 3.3 策略迭代算法 4.价值迭 ...

  5. 字符串上的动态规划算法--------单字符串的情况

    禁止字符串 考虑只由'A','G','C','T'四种字符组成的DNA字符串.给定一个长度为 k的字符串 S.请计算长度恰好为 n且不包含S的字符串的个数.输出个数mod 10009后的结果. 首先, ...

  6. 最大子段和——用蛮力算法,分治策略,动态规划算法三种求法(C语言)

    目录 一.题目 二.算法求解 1.蛮力算法 伪代码 算法分析 程序 2.分治策略 伪代码 算法分析 程序 3.动态规划算法 伪代码 算法分析 程序 一.题目 设A=<a1,a2,...,an&g ...

  7. 动态规划一:动态规划算法如何设计

    目录 历史 概念 初探 性质 记忆化搜索 动态规划算法如何设计 ? 加深理解 DAG最短路径 最长上升子序列 最长公共子序列 最大子段和 上楼梯 DP题目 实现目标:论文查重.拼写纠错.寻找最近加油站 ...

  8. 【论文阅读笔记】Myers的O(ND)时间复杂度的高效的diff算法

    前言 之前咱们三个同学做了个Simple-SCM,我负责那个Merge模块,也就是对两个不同分支的代码进行合并.当时为了简便起见,遇到文件冲突的时候,就直接按照文件的更改日期来存储,直接把更改日期较新 ...

  9. 矩阵连乘算法代码JAVA_矩阵连乘问题的动态规划算法(java)

    /** * 下面是矩阵连乘问题的动态规划算法 * 假设有6个矩阵: * A1 A2A3 A4 A5A6 * 30*35 35*15 15*5 5*10 10*20 20*25 则matrixChain ...

最新文章

  1. python如何去掉一个字符串两边的引号
  2. oracle-闪回技术2
  3. debian+pxe+preseed.cfg 安装配置
  4. Java 动态代理机制分析及扩展--转
  5. java web ftp上传_java web FTPClient实现上传文件到指定服务器
  6. 完成AOP 顶层设计-AopProxy
  7. S2SH CRUD 整合
  8. python怎么使用time模块_PYTHON的TIME模块使用
  9. c语言动态内存分配数组,【C】动态内存分配
  10. 用java打出矩形阵型的数字_java输出数字发散矩形
  11. POJ1039 Pipe
  12. 【网络协议】openR调研
  13. python面向对象编程的思想0727
  14. 使用对比学习处理大规模多模态单细胞数据
  15. 【今晚7点】:以歌会友,对话腾讯音乐天琴实验室 X 银河音效
  16. NVIDIA Jetson: GStreamer 和 openMAX(gst-omx) 插件
  17. RocketMQ 5.0 本地源码启动Cluster模式指南
  18. Linux 文件解压缩及权限管理
  19. 影视后期制作需要用到哪些软件?
  20. 一个本土科技精英的近况

热门文章

  1. 直播回顾 | 关于Apollo 5.0控制在环仿真技术的分享
  2. 知乎如何洞察你的真实喜好?首页信息流技术揭秘
  3. 机器学习101:我们天天都在说的机器学习,究竟该怎么入门?
  4. 妈呀!GitChat 发布 1.9 版本更新公告,这个红色简直亮瞎了我的眼...
  5. 注意!你的 Navicat 可能被投毒了...
  6. IDEA的debug功能,背后的原理是怎样的?
  7. 「薅」52图初探Linux通用知识
  8. 在MySQL数据库中,这4种方式可以避免重复的插入数据!
  9. 神奇的 SQL,Group By 真扎心,原来是这样!
  10. Elasticsearch 在互联网公司大量真实的应用案例