动态编程 - 复杂性

时间:2013-03-27 00:16:42

标签: algorithm complexity-theory dynamic-programming

我有一个家庭作业问题,我一直想弄清楚一段时间,而且我无法弄清楚我的生活。

我有一张尺寸为X * Y的纸张,以及一组尺寸较小的图案,其价格与之相关。我可以水平或垂直切割纸张,我必须找到优化的切割模式,以从纸张中获得最大的利润。

据我所知,应该有(X * Y)(X + Y +#ofPatterns)递归操作。复杂性应该是指数级的。有人可以解释一下原因吗?

我提出的伪代码如下:

Optimize( w, h ) {
best_price = 0
    for(Pattern p :  all patterns) {
        if ( p fits into this piece of cloth && p’s price > best price) {best_price = p’s price}
    }
    for (i = 1…n){
       L= Optimize( i, h );
       R= Optimize( w-i, h);
       if (L_price + R_price > best_price) { update best_price}
    }
    for (i = 1…n){
        T= Optimize( w, i );
        B= Optimize( w, h-i);
        if (T_price + B_price > best_price) { update best_price}
    }
return best_price;
}

2 个答案:

答案 0 :(得分:0)

递归情况呈指数级,因为您可以在开始时选择将纸张0剪切到最大宽度英寸或0到最大高度英寸,然后可选择剪切剩余部分(递归)。

这个问题听起来像这个杆切割问题更有趣,因为它涉及两个维度。

http://www.radford.edu/~nokie/classes/360/dp-rod-cutting.html

是一个很好的指南。阅读,这应该让你走在正确的轨道上,而不是公然回答你的作业。

递归时它为指数的相关部分:

This recursive algorithm uses the formula above and is slow
Code
    -- price array p, length n
    Cut-Rod(p, n)
        if n = 0 then
            return 0
        end if
        q := MinInt
        for i in 1 .. n loop
            q = max(q, p(i) + Cut-Rod(p, n-i)
        end loop
        return q

Recursion tree (shows subproblems): 4/[3,2,1,0]//[2,1,0],[1,0],0//[1,0],0,0//0
Performance: Let T(n) = number of calls to Cut-Rod(x, n), for any x
T(0)=0
T(n)=1+∑i=1nT(n−i)=1+∑j=0n−1T(j)
Solution: T(n)=2n

答案 1 :(得分:0)

在计算动态规划算法的复杂性时,我们可以将其分解为两个子问题:一个是计算子状态数;另一个是计算解决特定子问题的时间复杂度

但确实,当您不使用记忆方法时,具有多项式时间复杂性的算法会增加到指数时间复杂度,因为您不会重复使用先前计算过的信息。 (我很确定你从动态编程课程中理解这一部分)

无论您是使用记忆方法还是自下而上方法解决动态编程问题,时间复杂度都保持不变。我认为你遇到的麻烦是你试图在脑海中绘制函数调用图。相反,让我们尝试以这种方式估计函数调用的数量。

你说有(X * Y)(X + Y +#ofPatterns)递归调用。

嗯,是的,没有。

当你使用memoization方法时,只有这么多的递归调用。因为如果你已经调用并计算了某个Optimize(w0,h0),那么该值将被存储,并且下次另一个函数Optimize(w1,h1)调用Optimize(w0,h0)时,它将不再执行这些冗余工作。这就是时间复杂度多项式的原因。

但是在你当前的实现中,一个子问题Optimize(w0,h0)获得了许多冗余函数调用,这意味着算法中的递归调用数根本不是多项式的(举一个简单的例子,尝试绘制调用图递归Fibonacci数算法)。