迭代解决方案作为动态编程

时间:2015-05-11 18:23:33

标签: c++ algorithm

维基百科说这是关于动态编程的:

  

在数学,计算机科学,经济学和生物信息学中,动态规划是一种通过将其分解为更简单的子问题来解决复杂问题的方法。它适用于表现出重叠子问题和最优子结构特性的问题。如果适用,该方法所花费的时间远远少于不利用子问题重叠的其他方法(如深度优先搜索)。

以及Introduction to Algorithms (Cormen),我了解到dynamic programming是一种应用于解决repeating computations already been computed once的方法。用外行人的话说,

  

如果你要一次又一次地计算某些东西,最好将它存放在某个地方。

在Fibonacci上应用我可以按如下方式编写算法:

arr[3] = {1,1,1} //first two index for computation , last to keep track

fibbDyn(n){
    if(n>=1 || a[2]>n ) return n;    // return on base conditions
    else {
        res = arr[0] + fibbDyn(n-1); 
        arr[0]=arr[1];
        arr[1]=res; 
        arr[2]+=1;    // increment value by 1
        return res;
    }
} 

虽然我相信这个算法遵循动态编程的例子,因为它减少了在原始递归fibbonaci 版本中完成的额外计算:

 fibb(n){
    if (n>=1)return n;
    else return fibb(n-1) + fibb(n-2);
}

因为在每个递归步骤else return fibb(n-1) + fibb(n-2)进行两次单独调用,所以会重复多次计算。

迭代解决方案可能看起来像:

int FibonacciIterative(int n)
{
    if (n == 0) return 0;
    if (n == 1) return 1;

    int prevPrev = 0;
    int prev = 1;
    int result = 0;

    for (int i = 2; i <= n; i++)
    {
        result = prev + prevPrev;
        prevPrev = prev;
        prev = result;
    }
    return result;
}

所以我的问题是,Fibonacci问题的迭代解决方案是否会被归类为动态编程?

我对分歧的理由是,迭代解决方案不会展示Overlapping subproblems,例如递归解决方案。在迭代解决方案中,没有进行冗余和重复计算,因此它不应包含在动态编程中。

相关文章:optimal substructureoverlapping subproblemsdynamic programming

2 个答案:

答案 0 :(得分:1)

是。这只是Bottom Up动态编程的一个特例。您可以放弃您知道永远不会再使用的表条目,在Fibonacci的情况下,这意味着您只需要保留2个条目,然后您可以忘记它曾经是一个表并只使用两个命名变量。所以,它最终看起来不同,几乎太简单了。但该算法的结构仍然是DP。您所说的重叠子问题仍然存在,因为您使用每个结果两次(一次在prev时,再次在prevPrev时),最后除外。当然没有进行冗余计算,但那就是DP的想法 - 通过重用去除冗余计算。

对于允许动态编程的问题,存在一般性的“攻击计划”,即

  • 以递归方式陈述问题
  • (证明可以应用DP)
  • 确定子问题的排序,使它们在拓扑上排序(因此计算解决方案仅依赖于简单的解决方案和先前计算的解决方案,而不是未来的解决方案)
  • 如果订单不错,
  • 按顺序迭代填写表格。如果订单令人讨厌,也许保持自上而下的结构。

在Fibonacci的情况下,发生的事情是订单是微不足道的(这甚至不是特别罕见,但它使它看起来好像我们“没有真正做任何特别的事情”),并且依赖关系永远不会更多超过2个地方,所以必须记住的表的唯一部分是前两个单元格。因此,应用所有这些,您将获得众所周知的迭代算法。这并不意味着它不再是DP,这意味着DP非常成功。

至于属性(最佳子结构,重叠子问题),它们是问题的属性,无论你如何决定解决它们,它们都不会消失。但是你仍然可以在迭代算法中看到它们,正如我在第一段中指出的那样。

答案 1 :(得分:1)

Dynamic Programming阅读的维基百科页面上 - Dynamic programming in computer programming。这解释了两种方法,Top Down作为问题的递归公式,Bottom Up,我们迭代地生成解决更大问题的解决方案,当前解决方案存储在表中。在这种情况下,不需要表格,可以使用两个变量完成作业。 因此,在迭代方法的情况下,只有两个变量用于保存子问题的值;即,prev, (i-1 th)prevPrev, (i-2 th)。这里,prev和prevPrev用于找到第i个迭代的解(Bigger problem)。

result = prev + prevPrev;

只是第i次迭代结果的表示,它等于prev(i-1)+ prevPrev(i-2)。因此,子问题的重用也在迭代方法中进行。 这是动态编程的自下而上方法,递归方法是动态编程的Top Down方法。