【问题标题】:Optimal substructure in Dynamic Programing动态规划中的最优子结构
【发布时间】:2016-02-07 09:21:21
【问题描述】:

我一直在尝试理解动态编程,我理解的是DP有两个部分。

  1. 最佳子结构
  2. 重叠子问题

我理解第二个,但我无法理解第一个。

【问题讨论】:

    标签: dynamic-programming


    【解决方案1】:

    最优子结构意味着,在考虑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'/

    的最优解

    【讨论】:

    • 这是否意味着如果存在较小数量的解决方案则存在最优子结构?
    • @amit 你能告诉我是否需要最优子结构才能获得 DP 解决方案?如果是这种情况,那么阶乘为什么没有(据我所知)最优子结构的 DP 解决方案?
    • @Denson 他们确实有最优子结构,如果你指的是旅行商问题,例如,最优子结构在子集上。
    • @amit 你能解释一下什么是阶乘问题的最佳子结构吗?根据我从您的回答子问题事实(i)中可以理解的情况,只有一种可能的解决方案当然是最佳的?
    • @amit Traveling Salesman 优化子结构的问题对我来说很有意义..
    【解决方案2】:

    另一个很好的例子是在图中的每对顶点之间找到最短简单路径与在每对顶点之间找到最长简单路径之间的区别。 (“简单”意味着路径上的任何顶点都不能被访问两次;如果我们不将此约束用于问题的“最长”版本,那么只要图包含一个循环,我们就可以获得无限长的路径。)

    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 算法的挑战总是找到一种方法来定义子问题这会导致足够个不同的子问题(理想情况下,只有多项式),同时仍然保持重叠子问题和最优子结构的两个属性。

    【讨论】:

    • 对于给定的问题,我应该如何确定是否存在最优子结构?是通过hit and trial,求解更小的n然后找出来,还是有具体的方法来找到它?
    • 好吧,如果您想为 DP 使用特定的子问题定义,您必须证明存在最优子结构。但在你尝试用数学证明它之前,你可以尝试一些例子——也许有一些简单的反例会证明它是行不通的。
    • @j_random_hacker 你说“我们不能简单地将这两条路径粘合在一起以获得从 u 到 v 的最长简单路径。”你能给我一个图表的例子吗?我实在想不出一个。我开始相信最长的路径是最优的子结构......
    • @Ogen:首先也是最重要的,你有义务(或任何想尝试使用多时间 DP 解决最长路径的人)来证明这种不良情况不能 发生。无论如何,几乎任何足够大的图都会给出反例。这是一个小图:顶点 a、b 和 c 上的三角形图。从 a 到 c 的最长简单路径是 a-b-c;从 c 到 b 的最长简单路径是 c-a-b,所以要让 DP 工作,我们必须接受从 a 到 b 的最长简单路径是 a-b-c-a-b ——当然,这条路径并不简单。
    • @j_random_hacker 在您的第三段中,您提出了主张,因此举证责任实际上在您身上。另外,我认为这并不重要,因为该图是循环的。我说的是具有简单路径的非循环图。在这种情况下,最长路径问题确实具有最优子结构。看看这个答案cs.stackexchange.com/questions/56756/…
    【解决方案3】:

    简单来说:“最优性原则在解决优化问题时必须解决子问题,子问题的解决方案将成为优化问题的一部分”,如果问题可以由最优子问题解决意味着它由最优子结构组成。

    示例:假设在图中,源顶点是 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 而与目标节点无关,因为他们正在制作导致解决方案的子结构

    【讨论】:

      猜你喜欢
      • 2015-03-02
      • 1970-01-01
      • 1970-01-01
      • 2012-11-24
      • 2018-03-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多