我有一个家庭作业问题,我一直想弄清楚一段时间,而且我无法弄清楚我的生活。
我有一张尺寸为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;
}
答案 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数算法)。