动态规划和背包应用

时间:2012-09-27 17:23:04

标签: java algorithm optimization geometry dynamic-programming

我正在学习动态编程,我正在寻求解决以下问题,可以在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的算法。)

看起来我们有一种二维背包问题,但我认为可以用传统的背包算法解决它,将权重视为矩形区域。这看起来像是一种合理的方法吗?

这是我正在学习的课程的编程作业,所以请仅包括概念性讨论和/或伪代码来说明想法。

4 个答案:

答案 0 :(得分:14)

所以你从一个X * Y矩形开始。假设最佳解决方案涉及进行垂直(或水平)切割,那么您有两个新的矩形,其尺寸为X * Y1X * Y2Y1 + 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

}