我正在阅读Cormen等人的Introduction to Algorithms动态编程章节。我试图了解如何表征子问题的空间。他们举了两个动态编程的例子。这两个问题都有一个大小为n的输入
对于第一个问题,他们选择一个形式的子问题,在这个子问题中,他们进行长度为k的切割,假设切割产生的左子问题不能再进一步切割和正确的子问题可以进一步削减,从而给我们一个单一的子问题(nk)。
但是对于选择A i 类型的子问题的第二个问题... A j 其中1< = i< = j< = n。为什么他们选择为这个问题保持两端开放?为什么不关闭一端,只考虑大小的子问题(n-k)?为什么需要i和j而不是单个k分割?
答案 0 :(得分:3)
这是一门艺术。有许多类型的动态编程问题,要定义一种方法来确定我们想要解决子问题的空间维度并不容易。
这取决于子问题如何相互作用,而且取决于每个空间维度的大小。
动态编程是一个通用术语,用于描述子问题的缓存或记忆,以便更有效地解决更大的问题。但是有很多不同的问题可以通过动态编程以很多不同的方式解决,我无法解释所有这些问题,除非你有一个需要解决的特定动态编程问题。
我所能提出的建议是在解决问题时尝试:
一些可以描述为动态编程的算法包括:
答案 1 :(得分:2)
Vazirani关于动态规划的技术说明 http://www.cs.berkeley.edu/~vazirani/algorithms/chap6.pdf有一些有用的方法可以在给定输入的情况下创建子问题。我在下面的列表中添加了一些其他方法:
输入x_1,x_2,.. x_n。子问题是x_1 ... x_i。
输入x_1,x_2 .... x_n。子问题是x_i,... x_j。
输入x_1,x_2 ... x_n和y_1,y_2..y_m。子问题是x_1,x_2,.. x_i和y_1,y_2,.. y_j。
输入是一个有根的树。子问题是一个有根的子树。
输入是一个矩阵。子问题是与原始矩阵共享一个角的不同长度的子矩阵。
输入是一个矩阵。子问题是所有可能的子矩阵。
使用哪些子问题取决于问题。尝试这些已知的变化,看看哪一个最适合您的需求。