《图解算法》阅读15—动态规划

学习动态规划,他将问题分成小问题,并先着手解决这些小问题;学会设计问题的动态规划解决方案。

背包问题

回顾前面一小节的背包问题,假设一个小偷,背着一个可以装4磅东西的背包,如何盗窃使得商品的价值最高?

简单算法

尝试商品组合的全排列,找出价值最高的组合。这也是本人一直以来的思维方式,简单粗暴。恰好,上周的实习生面试,给自己敲响了警钟,这种完全不考虑运行时间和内存溢出的算法,在面试的过程中会被锤的很惨的。这样可行,但是运行的速度非常之慢!!!只要商品数量多到一定程度,这种算法就行不通。在第八章中,我们运用贪婪算法好到了近似解,但很可能不是最优解,这里我们进一步考虑,如何找到最优解呢?

动态规划

首先,我们明确动态规划的原理,先解决子问题,再逐步解决大问题。对于背包问题,先解决子背包问题,再解决大问题。
《图解算法》阅读15—动态规划_第1张图片
对于背包问题,每加入一个新的产品,需要进行考虑是否更新当前的背包。
可以偷商品的一部分吗? 答案是不可以!使用动态规划,要不考虑拿走所有的商品,要不考虑不拿。拿走部分商品可以考虑采用贪婪算法。
动态规划功能强大,它能够解决子问题并使用这些答案来解决大问题。但仅当每个子问题都是离散的,即不依赖于其他子问题时,动态规划猜管用。

最大公共子串(非常重要)

通过前面的动态规划问题,我们得到了如下启示。

  • 动态规划可以帮助我们找到在给定约束条件下最优解。在背包问题中,我们必须要在背包容量给定的情况下,偷到价值最高的商品。
  • 在问题可分解为彼此独立且离散的子问题时,就可以使用动态规划来解决,但是要找到解决问题的动态规划方案往往很难。
  • 每种动态规划解决方案都涉及网格。
  • 单元格中的值通常就是要优化的值。单元格的值为上品的价值。
  • 每个单元格都是一个子问题,因此应该考虑如何将问题分成子问题。

我们考虑如何应用动态规划解决求最大公共子串的问题?hish和vista都包含的最长子串是什么?

绘制单元格

  • 单元格中的值是什么?
  • 如何将这个问题划分为子问题?
  • 网格中的坐标轴是什么?
    《图解算法》阅读15—动态规划_第2张图片

填充网格

填充每个网格的单元格时,该使用什么样的公式呢?由于我们已经知道hish和fish的最长公共子串为ish,因此分析问题会相对简单一点。
我们知道在动态规划算法中,连接子问题和原问题的公式特别重要。这个时候可以使用费曼算法 :将问题写下来,好好思考,将答案写下来。实际上,经过这一段时间的学习,我也渐渐领悟到作者在书中所说的,根本没有找出计算公式的简单办法,必须通过尝试才能找出管用的公式。有些算法并非精确的解决步骤,而只是帮助我们理清思路的框架。
自己想了好久,思路还不是很清晰,当看到书中提供的图片立即对算法豁然开朗。但是自己还是有一些疑问的。比如图中fish的第四个字母和hish的第一个字母是匹配的却没有标注为1,自己认为当匹配的字符串比较大的时候,是会出问题的。
《图解算法》阅读15—动态规划_第3张图片

最常公共子序列

寻找最长公共子序列的算法如下图所示。
《图解算法》阅读15—动态规划_第4张图片

动态规划的应用

  • 生物学家根据最长公共序列来确定DNA链的相似性,进而判断两种动物或者疾病有多相似。
  • git diff等命令指出两个文件的差异,也是使用动态规划实现的。
  • 编辑距离指出了两个字符串的相似程度,也是使用动态规划计算得到的。编辑距离算法的用途很多,从拼写检查到判断用户上传的资料是否是盗版,都在其中。
  • 使用诸如Microsoft Word等具有断字功能的应用程序,同样使用动态规划。

小结

  • 需要在给定约束条件下优化某种指标时,动态规划很有用
  • 问题可以分解为离散子问题时,可使用动态规划来解决
  • 每种动态规划解决方案都涉及网格
  • 单元格中的值通常就是要优化的值
  • 每个单元格都是一个子问题,因此需要考虑如何将问题分解为子问题
  • 没有放之四海皆准的计算动态规划解决方案的公式,需要自己思考再思考,一般找到问题和子问题之间的关系就好

你可能感兴趣的:(算法)