【问题标题】:iterative solution as dynamic programming作为动态规划的迭代解决方案
【发布时间】:2015-07-22 09:16:57
【问题描述】:

维基百科这样说动态编程:

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

也从Introduction to Algorithms (Cormen),我了解到dynamic programming 是一种用于解决repeating computations 具有already been computed once 的方法。通俗地说,

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

将其应用于斐波那契我可以将其算法编写如下:

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;
}

所以我的问题是,斐波那契问题的迭代解决方案会被归类为动态规划吗?

我不同意的理由是,迭代解决方案不会展示Overlapping subproblems,例如递归解决方案正在展示。在迭代解决方案中,不会进行冗余和重复计算,因此不应将其包含在动态规划中。

相关文章:optimal substructureoverlapping subproblemsdynamic programming.

【问题讨论】:

  • 我也不是在征求意见,而不是强烈的主观答案,因此它遵循 SO 准则。在投票之前发表评论说明任何问题:)

标签: c++ algorithm


【解决方案1】:

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

对于允许动态规划的问题,有一个通用的“攻击计划”,即

  • 递归地陈述问题
  • (证明可以申请DP)
  • 确定子问题的排序,使其按拓扑排序(因此计算解决方案仅依赖于平凡的解决方案和先前计算的解决方案,而不是未来的解决方案)
  • 如果有一个很好的顺序,则按该顺序迭代地填充一个表。如果订单很烦人,可能会保留自上而下的结构。

在斐波那契的情况下,发生的事情是顺序是微不足道的(这甚至不是特别罕见,但它看起来好像我们“没有真正做任何特别的事情”),并且依赖关系永远不会返回更多多于 2 个位置,因此表中唯一需要记住的部分是前两个单元格。因此,应用所有这些,您将获得众所周知的迭代算法。这并不意味着它不再是 DP,而是意味着 DP 非常成功。

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

【讨论】:

  • 也许我第一次并不清楚。我在问 Fibb(n) 的迭代版本是否仍将是动态编程的一部分?我之前提供的代码是我改进的递归代码版本。所以我也提供了一个迭代版本。谢谢:)
  • @AbhinavGauniyal 将 Top Down DP 转变为 Bottom Up 当然不会减少 DP。
  • 没有。也许有些东西在翻译中丢失了。我在我的问题中提供了 3 个伪代码/代码。我在问最后一个(纯迭代)是否会被算作动态编程一个?因为我知道即兴递归的是 DP ,对吧?
  • @AbhinavGauniyal 迭代只是道德上相当于使用一些以前填充的条目填充表格,经典的自下而上 DP。只是它扔掉了大部分桌子。
【解决方案2】:

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

result = prev + prevPrev;

只是表示第 i 个迭代结果,等于 prev(i-1) + prevPrev(i-2)。因此,子问题的重用也在迭代方法中发生。 这是动态规划的自下而上的方法,递归的方法是动态规划的自顶向下的方法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-09-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-25
    • 1970-01-01
    相关资源
    最近更新 更多