📜  箱子堆放问题DP-22

📅  最后修改于: 2021-04-27 17:54:29             🧑  作者: Mango

您将获得一组n种类型的矩形3-D框,其中第i个框的高度为h(i),宽度w(i)和深度d(i)(所有实数)。您想创建一个尽可能高的盒子堆,但是如果下部盒子的2D底部的尺寸分别严格大于2个盒子的尺寸,则只能将一个盒子堆叠在另一个盒子的顶部。较高的盒子的D底座。当然,您可以旋转一个盒子,以便任何一侧都可以作为盒子的基础。也可以使用相同类型的盒子的多个实例。
资料来源: http //people.csail.mit.edu/bdean/6.046/dp/。该链接还包含视频,用于解释解决方案。

纸箱堆叠问题是LIS问题的一种变体。我们需要建立一个最大高度堆栈。

以下是问题说明中要注意的关键点:
1)仅当上方放置的箱子的宽度和深度分别小于下方放置的箱子的宽度和深度时,才可以将一个箱子放置在另一个箱子的顶部。
2)我们可以旋转盒子,使宽度小于深度。例如,如果有一个尺寸为{1x2x3}的框,其中1是高度,2×3是底数,则可能存在三种可能性:{1x2x3},{2x1x3}和{3x1x2}
3)我们可以使用多个盒子实例。这意味着,作为最大高度堆栈的一部分,我们可以对盒子进行两次不同的旋转。

以下是基于LIS问题的解决DP的解决方案

1)生成所有盒子的所有3个旋转。旋转数组的大小变为原始数组大小的3倍。为简单起见,我们认为宽度始终小于或等于深度。

2)以基面积的降序对上面生成的3n个框进行排序。

3)对箱子进行排序后,问题与具有最佳子结构属性的LIS相同。
MSH(i)=最大可能的堆栈高度,堆栈顶部带有方框i
MSH(i)= {最大值(MSH(j))+高度(i)},其中j width(i)和depth(j)> depth(i)。
如果没有这样的j,则MSH(i)=高度(i)

4)要获得总体最大高度,我们返回max(MSH(i)),其中0

以下是上述解决方案的实现。

C++
/* Dynamic Programming implementation of Box Stacking problem */
#include
#include
  
/* Representation of a box */
struct Box
{
  // h --> height, w --> width, d --> depth
  int h, w, d;  // for simplicity of solution, always keep w <= d
};
  
// A utility function to get minimum of two intgers
int min (int x, int y)
{ return (x < y)? x : y; }
  
// A utility function to get maximum of two intgers
int max (int x, int y)
{ return (x > y)? x : y; }
  
/* Following function is needed for library function qsort(). We
   use qsort() to sort boxes in decreasing order of base area. 
   Refer following link for help of qsort() and compare()
   http://www.cplusplus.com/reference/clibrary/cstdlib/qsort/ */
int compare (const void *a, const void * b)
{
    return ( (*(Box *)b).d * (*(Box *)b).w ) -
           ( (*(Box *)a).d * (*(Box *)a).w );
}
  
/* Returns the height of the tallest stack that can be
   formed with give type of boxes */
int maxStackHeight( Box arr[], int n )
{
   /* Create an array of all rotations of given boxes
      For example, for a box {1, 2, 3}, we consider three
      instances{{1, 2, 3}, {2, 1, 3}, {3, 1, 2}} */
   Box rot[3*n];
   int index = 0;
   for (int i = 0; i < n; i++)
   {
      // Copy the original box
      rot[index].h = arr[i].h;
      rot[index].d = max(arr[i].d, arr[i].w);
      rot[index].w = min(arr[i].d, arr[i].w);
      index++;
  
      // First rotation of box
      rot[index].h = arr[i].w;
      rot[index].d = max(arr[i].h, arr[i].d);
      rot[index].w = min(arr[i].h, arr[i].d);
      index++;
  
      // Second rotation of box
      rot[index].h = arr[i].d;
      rot[index].d = max(arr[i].h, arr[i].w);
      rot[index].w = min(arr[i].h, arr[i].w);
      index++;
   }
  
   // Now the number of boxes is 3n
   n = 3*n;
  
   /* Sort the array 'rot[]' in non-increasing order
      of base area */
   qsort (rot, n, sizeof(rot[0]), compare);
  
   // Uncomment following two lines to print all rotations
   // for (int i = 0; i < n; i++ )
   //    printf("%d x %d x %d\n", rot[i].h, rot[i].w, rot[i].d);
  
   /* Initialize msh values for all indexes 
      msh[i] --> Maximum possible Stack Height with box i on top */
   int msh[n];
   for (int i = 0; i < n; i++ )
      msh[i] = rot[i].h;
  
   /* Compute optimized msh values in bottom up manner */
   for (int i = 1; i < n; i++ )
      for (int j = 0; j < i; j++ )
         if ( rot[i].w < rot[j].w &&
              rot[i].d < rot[j].d &&
              msh[i] < msh[j] + rot[i].h
            )
         {
              msh[i] = msh[j] + rot[i].h;
         }
  
  
   /* Pick maximum of all msh values */
   int max = -1;
   for ( int i = 0; i < n; i++ )
      if ( max < msh[i] )
         max = msh[i];
  
   return max;
}
  
/* Driver program to test above function */
int main()
{
  Box arr[] = { {4, 6, 7}, {1, 2, 3}, {4, 5, 6}, {10, 12, 32} };
  int n = sizeof(arr)/sizeof(arr[0]);
  
  printf("The maximum possible height of stack is %d\n",
         maxStackHeight (arr, n) );
  
  return 0;
}


Java
/* Dynamic Programming implementation 
of Box Stacking problem in Java*/
import java.util.*;
  
public class GFG {
      
    /* Representation of a box */
    static class Box implements Comparable{
      
        // h --> height, w --> width,
        // d --> depth
        int h, w, d, area;
          
        // for simplicity of solution,
        // always keep w <= d
  
        /*Constructor to initialise object*/
        public Box(int h, int w, int d) {
            this.h = h;
            this.w = w;
            this.d = d;
        }
          
        /*To sort the box array on the basis
        of area in decreasing order of area */
        @Override
        public int compareTo(Box o) {
            return o.area-this.area;
        }
    }
  
    /* Returns the height of the tallest
    stack that can be formed with give 
    type of boxes */
    static int maxStackHeight( Box arr[], int n){
          
        Box[] rot = new Box[n*3];
          
        /* New Array of boxes is created - 
        considering all 3 possible rotations, 
        with width always greater than equal
        to width */
        for(int i = 0;i < n;i++){
            Box box = arr[i];
              
            /* Orignal Box*/
            rot[3*i] = new Box(box.h, Math.max(box.w,box.d), 
                                    Math.min(box.w,box.d));
              
            /* First rotation of box*/
            rot[3*i + 1] = new Box(box.w, Math.max(box.h,box.d), 
                                       Math.min(box.h,box.d));
              
            /* Second rotation of box*/
            rot[3*i + 2] = new Box(box.d, Math.max(box.w,box.h),
                                       Math.min(box.w,box.h));
        }
          
        /* Calculating base area of 
        each of the boxes.*/
        for(int i = 0; i < rot.length; i++)
            rot[i].area = rot[i].w * rot[i].d;
          
        /* Sorting the Boxes on the bases 
        of Area in non Increasing order.*/
        Arrays.sort(rot);
          
        int count = 3 * n;
          
        /* Initialize msh values for all 
        indexes 
        msh[i] --> Maximum possible Stack Height
                   with box i on top */
        int[]msh = new int[count];
        for (int i = 0; i < count; i++ )
            msh[i] = rot[i].h;
          
        /* Computing optimized msh[] 
        values in bottom up manner */
        for(int i = 0; i < count; i++){
            msh[i] = 0;
            Box box = rot[i];
            int val = 0;
              
            for(int j = 0; j < i; j++){
                Box prevBox = rot[j];
                if(box.w < prevBox.w && box.d < prevBox.d){
                    val = Math.max(val, msh[j]);
                }
            }
            msh[i] = val + box.h;
        }
          
        int max = -1;
          
        /* Pick maximum of all msh values */
        for(int i = 0; i < count; i++){
            max = Math.max(max, msh[i]);
        }
          
        return max;
    }
      
    /* Driver program to test above function */
    public static void main(String[] args) {
          
        Box[] arr = new Box[4];
        arr[0] = new Box(4, 6, 7);
        arr[1] = new Box(1, 2, 3);
        arr[2] = new Box(4, 5, 6);
        arr[3] = new Box(10, 12, 32);
          
        System.out.println("The maximum possible "+
                           "height of stack is " + 
                           maxStackHeight(arr,4));
    }
}
  
// This code is contributed by Divyam


Python3
# Dynamic Programming implementation
# of Box Stacking problem
class Box:
      
    # Representation of a box
    def __init__(self, h, w, d):
        self.h = h
        self.w = w
        self.d = d
  
    def __lt__(self, other):
        return self.d * self.w < other.d * other.w
  
def maxStackHeight(arr, n):
  
    # Create an array of all rotations of 
    # given boxes. For example, for a box {1, 2, 3}, 
    # we consider three instances{{1, 2, 3},
    # {2, 1, 3}, {3, 1, 2}}
    rot = [Box(0, 0, 0) for _ in range(3 * n)]
    index = 0
  
    for i in range(n):
  
        # Copy the original box
        rot[index].h = arr[i].h
        rot[index].d = max(arr[i].d, arr[i].w)
        rot[index].w = min(arr[i].d, arr[i].w)
        index += 1
  
        # First rotation of the box
        rot[index].h = arr[i].w
        rot[index].d = max(arr[i].h, arr[i].d)
        rot[index].w = min(arr[i].h, arr[i].d)
        index += 1
  
        # Second rotation of the box
        rot[index].h = arr[i].d
        rot[index].d = max(arr[i].h, arr[i].w)
        rot[index].w = min(arr[i].h, arr[i].w)
        index += 1
  
    # Now the number of boxes is 3n
    n *= 3
  
    # Sort the array 'rot[]' in non-increasing 
    # order of base area
    rot.sort(reverse = True)
  
    # Uncomment following two lines to print 
    # all rotations 
    # for i in range(n):
    #     print(rot[i].h, 'x', rot[i].w, 'x', rot[i].d)
  
    # Initialize msh values for all indexes
    # msh[i] --> Maximum possible Stack Height 
    # with box i on top
    msh = [0] * n
  
    for i in range(n):
        msh[i] = rot[i].h
  
    # Compute optimized msh values
    # in bottom up manner
    for i in range(1, n):
        for j in range(0, i):
            if (rot[i].w < rot[j].w and 
                rot[i].d < rot[j].d):
                if msh[i] < msh[j] + rot[i].h:
                    msh[i] = msh[j] + rot[i].h
  
    maxm = -1
    for i in range(n):
        maxm = max(maxm, msh[i])
  
    return maxm
  
# Driver Code
if __name__ == "__main__":
    arr = [Box(4, 6, 7), Box(1, 2, 3),
           Box(4, 5, 6), Box(10, 12, 32)]
    n = len(arr)
    print("The maximum possible height of stack is",
           maxStackHeight(arr, n))
  
# This code is contributed by vibhu4agarwal


输出:

The maximum possible height of stack is 60

在上述程序中,给定的输入框为{4,6,7},{1,2,3},{4,5,6},{10,12,32}。以下是框的所有旋转,它们按基本区域的降序排列。

10 x 12 x 32
   12 x 10 x 32
   32 x 10 x 12
   4 x 6 x 7
   4 x 5 x 6
   6 x 4 x 7
   5 x 4 x 6
   7 x 4 x 6
   6 x 4 x 5
   1 x 2 x 3
   2 x 1 x 3
   3 x 1 x 2

高度60通过盒{{3,1,2},{1,2,3},{6,4,5},{4,5,6},{4,6,7},{32获得,10,12},{10,12,32}}

时间复杂度:O(n ^ 2)
辅助空间:O(n)