随着我对动态规划的理解,我发现在特定情况下开发最优子结构的概念更容易,更容易。例如,通过找到乘以矩阵链的最佳排序,我理解(遗憾的是,这可以帮助我)计算Ai * Ai + 1 * ... * Aj所需的最小乘法次数可以找到通过找到i和j之间的分割/ parenetheses放置点k来最小化Ai * ... Ak和Ak + 1 ... * Aj所需的乘法之和,加上所需的成本与实际尺寸。换句话说,M(i,j)= mink(M(i,k)+ M(k + 1,j)+ di-1dkdj)。
同样,在找到一个字符串的最长回文子串时,最佳子结构是索引i和j与输入数组之间的最大长度回文的长度l [i,j]是2 + l [i + 1,j-1],当i和j处的元素相同并因此可以相加时,或者l [i + 1,j],l [i,j-1]的最大值(如果我是正确的话)混合任何东西......)
但是,在任何情况下,我如何将其转换为算法以找到理想序列的长度,例如上述甚至其内容?我基本上只是运行循环来制表所有内容,然后基本上“选择”从表中需要什么?使用矩阵链,这似乎正是要做的事情,但对于回文,我对如何构造循环有点困惑。
谢谢!
答案 0 :(得分:1)
我基本上只是运行循环来制表所有内容,然后基本上“选择”从表中需要什么?
简而言之,是的。动态编程依赖于两件事:使原始问题变小(在你的问题中有详细描述)和基本情况:解决方案明显的那些(几乎总是很小的)情况,不再需要将问题分成子问题。例如,在矩阵乘法示例中,一旦子问题减少到2个矩阵,您就不再有选择: 将它们按原样相乘。在你的回文示例中,我会选择一个长度为1的子串的基本情况,这显然是一个回文。
因此,一旦创建了memoization数组/矩阵等,您通常要做的是在该数组中设置基本案例值,然后让算法运行。结束条件通常是当你到达数组中的正确点时,或者当没有任何东西需要计算时(此时你选择'你需要从数组/矩阵中得到什么等)
我希望这具体到有用。