我过去曾研究过经典的DP问题和算法(硬币,最长的子序列,最长的子序列等)。
我知道这些算法具有实际应用(即遗传算法,仅举一例)。我所怀疑的是,如果这些算法在现代计算机科学中具有实际应用,其中输入的大小非常大并且只能在一台机器上解决问题。
我的观点是这些算法很难并行化(即Parallel Dynamic Programming),并且大多数公式中的内存占用都是二次的,这使得很难处理相当大的输入。
任何人都有这个真实世界的用例吗?
答案 0 :(得分:5)
实际应用:diff
。这是一个重要的Linux实用程序,它通过使用DP算法解决longest common subsequence问题来查找两个文件之间的差异。
使用DP算法,因为在许多情况下,它们是唯一实用的解决方案。此外,它们没有任何问题。
内存使用情况:通常,可以使用滑动窗口来显着降低内存使用量。 Fibonacci,当使用天真的自下而上的DP解决时,需要O(n)内存。一个滑动窗口将其改进为O(1)内存(我知道magical constant time solution,但这不是重点)。
并行化:自上而下的DP通常很容易并行化。自下而上可能会也可能不会。 @ amit的例子(并行化最长公共子序列)是一个很好的例子,只要先前的对角线已知,任何给定对角线的图块都可以独立解决。
答案 1 :(得分:1)
The longest common subsequence问题和Longest common substring problem对于分析字符串[例如分析基因序列]有时很重要。并且可以使用动态编程有效地解决它们。
注意你可以并行化这个算法:你可以在对角线上进行迭代[从左,从下到右,向上] - 所以总共2n-1
次迭代。并且在每个对角线上:每个单元格不依赖于此对角线中的其他单元格 - 因此可以在此处进行并行化,每个线程将在此对角线中具有一个单元块。
请注意,使用此方法的数据同步也很少:每个线程只需将数据传输到“相邻线程”,因此即使内存未共享也可以完成。
此外,正如@larsmans所提到的这两个问题都可以使用线性空间 - 在每个点上你只需要“记住”当前的+ 2个最后对角线,而不是整个矩阵。
使用动态编程解决的另一个常见问题是polynomial interpolation。可以使用Newton Interpolation高效地完成插值,divided differences首先需要计算{{3}} - 它是使用动态编程构建的。