Problema de apilamiento de cajas | DP-22 – Part 1

Se le da un conjunto de n tipos de cajas tridimensionales rectangulares, donde la i^-ésima caja tiene una altura h (i), un ancho w (i) y una profundidad d (i) (todos números reales). Desea crear una pila de cajas que sea lo más alta posible, pero solo puede apilar una caja encima de otra caja si las dimensiones de la base 2-D de la caja inferior son estrictamente mayores que las de la base 2-D. D base de la caja superior. Por supuesto, puede rotar una caja para que cualquier lado funcione como su base. También está permitido usar varias instancias del mismo tipo de caja. 
Fuente: http://people.csail.mit.edu/bdean/6.046/dp/ . El enlace también tiene un video para una explicación de la solución.
 

C++

/* Dynamic Programming implementation of Box Stacking problem */
#include<stdio.h>
#include<stdlib.h>
  
/* 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 integers
int min (int x, int y)
{ return (x < y)? x : y; }
  
// A utility function to get maximum of two integers
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<Box>{
      
        // 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];
              
            /* Original 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

C++

/* Dynamic Programming top-down implementation of Box
 * Stacking problem */
#include <bits/stdc++.h>
using namespace std;
  
/* Representation of a box */
class Box {
public:
    int length;
    int width;
    int height;
};
  
// dp array
int dp[303];
  
/*
    boxes -> vector of Box
    bottom_box_index -> index of the bottom box
    index -> index of current box
*/
/* NOTE: we can use only one variable in place of bottom_box_index and index
     but it has been avoided to make it simple */
int findMaxHeight(vector<Box>& boxes, int bottom_box_index, int index)
{
  
    // base case
    if (index < 0)
        return 0;
  
    if (dp[index] != -1)
        return dp[index];
  
    int maximumHeight = 0;
  
    // recurse
    for (int i = index; i >= 0; i--) {
  
        // if there is no bottom box
        if (bottom_box_index == -1
  
            // or if length & width of new box is < that of
            // bottom box
            || (boxes[i].length
                    < boxes[bottom_box_index].length
                && boxes[i].width
                       < boxes[bottom_box_index].width))
  
            maximumHeight
                = max(maximumHeight,
                      findMaxHeight(boxes, i, i - 1)
                          + boxes[i].height);
    }
  
    return dp[index] = maximumHeight;
}
  
/* wrapper function for recursive calls which
Returns the height of the tallest stack that can be
formed with give type of boxes */
int maxStackHeight(int height[], int width[], int length[],
                   int types)
{
    // creating a vector of type Box class
    vector<Box> boxes;
  
    // Initialize dp array with -1
    memset(dp, -1, sizeof(dp));
  
    Box box;
  
    /* 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}} */
    for (int i = 0; i < types; i++) {
  
        // copy original box
        box.height = height[i];
        box.length = max(length[i], width[i]);
        box.width = min(length[i], width[i]);
  
        boxes.push_back(box);
  
        // First rotation of box
        box.height = width[i];
        box.length = max(length[i], height[i]);
        box.width = min(length[i], height[i]);
  
        boxes.push_back(box);
  
        // Second rotation of box
        box.height = length[i];
        box.length = max(width[i], height[i]);
        box.width = min(width[i], height[i]);
  
        boxes.push_back(box);
    }
  
    // sort by area in ascending order .. because we will be dealing with this vector in reverse
    sort(boxes.begin(), boxes.end(), [](Box b1, Box b2) {
        // if area of box1 < area of box2
        return (b1.length * b1.width)
               < (b2.length * b2.width);
    });
    
   // Uncomment following two lines to print all rotations
    //for (int i = boxes.size() - 1; i >= 0; i-- )
   //   printf("%d x %d x %d\n", boxes[i].length, boxes[i].width, boxes[i].height);
  
    return findMaxHeight(boxes, -1, boxes.size() - 1);
}
  
int main()
{
  
    // where length, width and height of a particular box
    // are at ith index of the following arrays
    int length[] = { 4, 1, 4, 10 };
    int width[] = { 6, 2, 5, 12 };
    int height[] = { 7, 3, 6, 32 };
  
    int n = sizeof(length) / sizeof(length[0]);
  
    printf("The maximum possible height of stack is %d\n",
           maxStackHeight(height, length, width, n));
  
    return 0;
}

Publicación traducida automáticamente

Artículo escrito por GeeksforGeeks-1 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *