DP求和所有节点组合

时间:2017-07-22 14:44:22

标签: dynamic-programming

给定每个节点的树和值,我们如何获得每个可能路径的总和?

  A
  |
  B

在上面的树中将有4条这样的路径:A,B,A-B,B-A。 每个节点都会分配一个值:A: 3, B: 2

预期输出应为:3 + 2 +(3 + 2)+(2 + 3)

这个问题的一个天真的解决方案是从源到目标(对于每个可能的组合)进行DFS并通过添加DFS结果来获得总和,但我相信这个问题可以通过DP更有效地解决,但是不要真的有很多DP经验。

1 个答案:

答案 0 :(得分:1)

这个有一个很好的解决方案,它不涉及(很多)动态编程:

您可以计算每个节点在路径中出现的频率。让我们以n=5个节点为例:

    A
    |
    B
   / \
  C   D
      |
      E

叶子ACE的计算非常简单。它们仅出现在以此节点开头或结尾的路径中。有2n - 1 = 9个路径-1,因为路径A的开头和结尾都是A,因此会在2*n中计算两次。

对于内部节点,它变得有点棘手。让我们先看看节点D。当然D出现在所有路径中,以D开头或结尾。所以我们再次拥有2n - 1 = 9个路径。但现在也可能是D出现在路径中间的某个地方。例如。在路径A-B-D-E中。只有当路径从子树ABC中的某个位置开始并以子树E或相反的方式结束时,才会发生这种情况。 Combinatorics告诉我们,有size(ABC)*size(E) + size(E)*size(ABC) = 2*size(ABC)*size(E) = 2*3*1 = 6多个。因此,D恰好出现在9 + 6 = 15个路径中。

对于节点B,它仍然有点棘手。从2n - 1 = 9开始或结束的路径再次出现B(每个节点都是如此)。但是B再次出现在路径中间的某个地方。要实现此目的,路径必须从其中一个子树ACDE开始,并以不同的方式结束。所以有2*size(A)*size(C) + 2*size(C)*size(DE) + 2*size(DE)*size(A) = 2*1*1 + 2*1*2 + 2*2*1 = 2 + 4 + 4 = 10个可能的路径。通过一些数学运算,您可以看到这与(n-1)^2 - size(A)^2 - size(C)^2 - size(DE)^2相同。因此,总共节点出现在9 + 10 = 19路径中。

您要计算的值为9*value(A) + 19*value(B) + 9*value(C) + 15*value(D) + 9*value(E)

通过一次深度优先搜索,您可以使用动态编程计算所有子树的大小,并使用这两个公式计算每个节点的出现次数。