我正在学习动态编程,我正在寻求解决以下问题,可以在http://www.cs.berkeley.edu/~vazirani/algorithms/chap6.pdf找到:
您将得到一块尺寸为X×Y的矩形布,其中X和Y为正整数,以及可以使用布制作的n个产品列表。对于[1,n]中的每个产品,您知道需要一个尺寸为ai by bi的矩形布料,并且该产品的最终销售价格为ci。假设ai,bi和ci都是正整数。你有一台机器可以将任何矩形布块水平或垂直切成两块。设计一种算法,找到切割X×Y布料的最佳策略,以便由最终产品制成的产品给出最大的销售价格总和。您可以根据需要自由制作给定产品的副本,如果需要,可以不制作任何副本。 (来自Dasgupta,Papadimitriou和Vazirani的算法。)
看起来我们有一种二维背包问题,但我认为可以用传统的背包算法解决它,将权重视为矩形区域。这看起来像是一种合理的方法吗?
这是我正在学习的课程的编程作业,所以请仅包括概念性讨论和/或伪代码来说明想法。
答案 0 :(得分:14)
所以你从一个X * Y
矩形开始。假设最佳解决方案涉及进行垂直(或水平)切割,那么您有两个新的矩形,其尺寸为X * Y1
,X * Y2
为Y1 + Y2 = Y
。由于您希望最大化您的利润,您需要最大化这些新矩形(最佳子结构)的利润。因此,您的初始递归如下:f(X, Y) = max(f(X, Y1) + f(X, Y2), f(X1, Y) + f(X2, Y))
表示X1, X2
(水平切割)和Y1, Y2
(垂直切割)的所有可能值。
现在问题是我什么时候才能决定制作产品?当其中一个尺寸等于当前矩形的尺寸之一时,您可以决定制作产品(为什么?因为如果这是不成立的,最佳的解决方案包括制作这个产品,然后迟早你需要做一个垂直(或水平)切割,这种情况已经在初始递归中处理了,所以你做了适当的切割和你有一个新的矩形X * Y1
(或X1 * Y
),具体取决于你为获得产品所做的削减,在这种情况下,递归变为f(X, Y) = cost of product + f(X1, Y)
。
原始问题的解决方案是f(X, Y)
。此dp解决方案的运行时间为O(X * Y * (X + Y + number of available products))
:您有X * Y
个可能的矩形,对于每个这样的矩形,您尝试每次可能的切割(X + Y
)并尝试制作其中一个这个矩形的产品。
另外,请查看2010年ICPC世界总决赛中的类似问题:分享巧克力。
答案 1 :(得分:3)
我认为你应该把重点放在机器将布料切成两块的事实上。什么能适合这两件?请考虑以下事项:
+-------------+-------------------+
| | Piece B |
| | |
| Piece A +----------+--------+
| | | |
| | | |
| | | Piece |
+-------------+----------+ C |
| | |
| Piece D | |
+------------------------+--------+
这四个适合布料,但不能以三种切割方式实现。 (可能不同的安排会允许使用这些特定的部分;将其视为概念图,而不是扩展。我的ascii艺术技能今天有限。)
专注于“切割的位置”应该为您提供动态编程解决方案。祝你好运。
答案 2 :(得分:2)
请在 Rect()函数中包含大小为(0, something)
或(something, 0)
的矩形的必要条件。
答案 3 :(得分:1)
optimize(){
Rectangle memo[width][height]
optimize(0,0,totalwidth, totalheight, memo)
}
优化(x,y,宽度,高度,备忘录){
if memo[width][height] != null
return memo[width][height]
rect = new Rectangle(width, height, value = 0)
for each pattern {
//find vertical cut solution
leftVerticalRect = optimize (x, y + pattern.height, pattern.width, height-pattern.height,memo)
rightVerticalRect = optimize(x + pattern.width, y, width-pattern.width, height)
verticalcut = new Cut(x + pattern.width, y, x + pattern.width, y + height)
//find horizontal cut solution
topHorizontalRect = optimize ( --parameters-- )
bottomHortizonalRect = optimize( --parameters--)
horizontalcut = new Cut( --parameters--)
//see which solution is more optimal
if (leftVerticalRect.val + rightVerticalRect.val > topHorizontalRect.val + bottomHorizontalRect.val)
subprobsolution = vertical cut solution
else
subprobsolution = horizontal cut solution
//see if the solution found is greater than previous solutions to this subproblem
if (subprobsolution.value + pattern.value > rect.value) {
rect.subrect1 = subprobsolutionrect1
rect.subrect2 = subprobsolutionrect2
rect.pattern = pattern
rect.cut = subprobsolutioncut
rect.value = rect.subrect1.value + rect.subrect2.value + rect.pattern.value
}
}
memo[width][height] = rect
return rect
}