前几天我正在看CLRS只是为了让我的思绪更加清醒,并碰到经典的切杆问题。
经典的自下而上解决方案如下:
1: let r[0..n] be a new array
2: r[0] = 0
3: for j = 1 to n
4: q = -1
5: for i = 1 to j
6: q = max(q, p[i] + r[j-i])
7: r[j] = q
8: return r[n]
现在有一些我一直在想的事情。为什么我们继续在L.6上重用p [i]?我的意思是让我们说我们有j = 4然后它会计算以下组合:
1 + 3
2 + 2
3 + 1
4 + 0
真正两次计算“3 + 1”的重点是什么。我建议的不是使用p []而只使用r []并停在楼层(j / 2)。
1: let r[0..n] be a new array
2: r[0] = 0
3: for j = 1 to n
4: q = p[j]
5: for i = 1 to floor(j/2)
6: q = max(q, r[i] + r[j-i])
7: r[j] = q
8: return r[n]
有人看到这种方法有问题吗?
谢谢,
答案 0 :(得分:2)
您的优化没有任何问题。我已经看过它在杆切割问题中曾多次使用/提到过(这里只是一个例子:http://users.csc.calpoly.edu/~dekhtyar/349-Spring2010/lectures/lec09.349.pdf)。没有完美的教科书这样的东西。它可能是CLRS的一个错误,或者他们只是觉得提到这样的优化会使这本书变得混乱。
通常,这些入门书籍将专注于高级概念,并将发现这些微不足道的优化留给读者。考虑冒泡排序:不是每个人都会提到内部循环j
只需要达到i
的简单优化这一事实。
答案 1 :(得分:0)
我知道这是一个老问题,但我觉得这个问题只有一半回答。回答你问题的第一部分:
真正计算“3 + 1”的重点是什么
我想指出书中有一个脚注说明,
如果我们要求按照非减小尺寸的顺序切割件, 会有更少的方法来考虑。对于n = 4,我们会考虑 只有5种这样的方式。 [...]然而,我们不会进一步探讨这一调查。
您的优化没有任何问题。我认为这本书被故意排除在外,以便让学生更容易解决后续练习。
答案 2 :(得分:0)
您的优化很好。 使用单个循环而不是2个循环有一种更有效的方法:
1:let r[0..n] be a new array
2:r[0] = 0
3:q=-1
4:for j = 1 to floor(n/2)
5:q = max(q, r[j] + r[n-j])
6:r[j] = q
7:return r[floor(n/2)]