【发布时间】:2016-02-07 09:21:21
【问题描述】:
我一直在尝试理解动态编程,我理解的是DP有两个部分。
- 最佳子结构
- 重叠子问题
我理解第二个,但我无法理解第一个。
【问题讨论】:
我一直在尝试理解动态编程,我理解的是DP有两个部分。
我理解第二个,但我无法理解第一个。
【问题讨论】:
最优子结构意味着,在考虑n' < n 元素时,任何大小为n 的问题的最优解都基于同一问题的最优解。
这意味着,在为大小为n 的问题构建解决方案时,您将问题拆分为更小的问题,其中一个大小为n'。现在,您只需考虑基于最优子结构属性的n' 的最优解,而不是所有可能的解。
一个例子是knapsack problem:
D(i,k) = min { D(i-1,k), D(i-1,k-weight(i)) + cost(i) }
这里的最优子结构假设是D(i,k) 只能检查D(i-1,k) 的最优解,不考虑没有最优解。
这不成立的一个例子是Vertex Cover problem。
如果你有一个图 G=(V,E),假设你有一个子图 G'=(V',E[intersection]V'xV') 的最优解,这样V' <= V - G 的最优解不必由G'/
【讨论】:
另一个很好的例子是在图中的每对顶点之间找到最短简单路径与在每对顶点之间找到最长简单路径之间的区别。 (“简单”意味着路径上的任何顶点都不能被访问两次;如果我们不将此约束用于问题的“最长”版本,那么只要图包含一个循环,我们就可以获得无限长的路径。)
Floyd-Warshall algorithm 可以通过利用以下事实有效地计算第一个问题的答案:如果从 u 到 v 的路径是最短的,那么对于这条路径上的任何顶点 x,它必须 em> 是从 u 到 x 的子路径和从 x 到 v 的子路径也是最短可能的。 (假设相反,从 u 到 v 的“最短”路径上有一个顶点 x,因此从 u 到 x 的子路径不是最短的:那么就有可能找到从 u 到 x 的其他更短的路径-- 这也可以用来使从 u 到 v 的整体路径缩短相同的量,因此原始的 u 到 v 路径毕竟不可能是最短的。)这意味着当寻找最短的 u-to-v 路径,该算法只需要考虑在其他顶点对之间的最短可能(即最优)子路径中构建它 - 而不是从更大数量的 all 这样的子路径。
相比之下,考虑确定图中任意两个顶点之间最长简单路径的问题。同样,如果从 u 到 v 的最长路径经过某个顶点 x,那么从 u 到 x 以及从 x 到 v 的子路径也必然也是最长可能的,这是否同样正确?不幸的是,从 u 到 x 的最长路径很可能在其内部使用了一些顶点,这些顶点也是从 x 到 v 的最长路径所需要的,这意味着我们不能简单地将这两条路径粘合在一起以获得最长的简单从 u 到 v 的路径。
作为一般规则,我们总是可以通过选择使用要解决的子问题的足够详细的定义来“绕过”这个问题:在这种情况下,而不是要求两个给定顶点 u 和 v 之间的最长路径,我们可以求两个给定顶点 u 和 v 之间的最长路径,它只使用给定集合 S 中的顶点。以前我们可以构建一个带有两个参数的函数shortest(u, v),现在我们必须构建一个带有三个参数的函数longest(u, v, S);然后可以使用longest(u, v, V) 计算 2 个顶点 u 和 v 之间的总体最长路径,其中 V 是图的整个顶点集。有了这个新定义,现在可以再次通过仅将最优解决方案与子问题组合来产生最优解决方案,因为我们可以确保我们只尝试将由 S 集不相交的子问题产生的路径粘合在一起。我们现在可以正确确定从 u 到 v 的最长路径,它只使用 S 中的顶点,即longest(u, v, S),通过计算 S 中所有顶点 x 的最大值,以及划分 S 的所有方式- {x} 分成 longest(u, x, A) + longest(x, v, B) 的两个子集 A 和 B。
不幸的是,现在有指数级的子问题需要解决,因为一组 n 个顶点可以以 2^(n-1) 种不同的方式进行划分。 (刚刚描述的算法对于这个问题可能不是最有效的 DP,但即使是最有效的已知 DP 在其运行时间中仍然具有这个指数因子。)设计 DP 算法的挑战总是找到一种方法来定义子问题这会导致足够个不同的子问题(理想情况下,只有多项式),同时仍然保持重叠子问题和最优子结构的两个属性。
【讨论】:
简单来说:“最优性原则在解决优化问题时必须解决子问题,子问题的解决方案将成为优化问题的一部分”,如果问题可以由最优子问题解决意味着它由最优子结构组成。
示例:假设在图中,源顶点是 s,目标是 d。 我们必须找到最短的(s,d)
graph is
a g
b e h d
s c f i
d
length(s,a)=14
length(s,b)=10
length(s,c)=1
length(s,d)=6
length(c,b)=1
注意:(s,e) 或 (s,f) 没有直接边。 在考虑为此寻找算法时,如果我们正在编写一个优先级队列结构,它将以最少的总 PATH_Length 遍历。 我们将从源顶点分配每个顶点 PATH_LENGTH。
如果新的路径长度
Example : Len(s,b) > Len(s,a)+Len(a,b);
reset len(s,b)=2;
来自 S 的相邻节点创建路径以获得最小 path_length 而与目标节点无关,因为他们正在制作导致解决方案的子结构。
【讨论】: