Dynamic Programming | Set 22 (Box Stacking Problem) | GeeksforGeeks


Related: Stack of Boxes
Dynamic Programming | Set 22 (Box Stacking Problem) | GeeksforGeeks
You are given a set of n types of rectangular 3-D boxes, where the i^th box has height h(i), width w(i) and depth d(i) (all real numbers). You want to create a stack of boxes which is as tall as possible, but you can only stack a box on top of another box if the dimensions of the 2-D base of the lower box are each strictly larger than those of the 2-D base of the higher box. Of course, you can rotate a box so that any side functions as its base. It is also allowable to use multiple instances of the same type of box.
1) Generate all 3 rotations of all boxes. The size of rotation array becomes 3 times the size of original array. For simplicity, we consider depth as always smaller than or equal to width.
2) Sort the above generated 3n boxes in decreasing order of base area.
3) After sorting the boxes, the problem is same as LIS with following optimal substructure property.
MSH(i) = Maximum possible Stack Height with box i at top of stack
MSH(i) = { Max ( MSH(j) ) + height(i) } where j < i and width(j) > width(i) and depth(j) > depth(i).
If there is no such j then MSH(i) = height(i)
4) To get overall maximum height, we return max(MSH(i)) where 0 < i < n
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] = arr[i];
      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 decreasing order, using library
      function for quick sort */
   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;
}
Source: http://people.csail.mit.edu/bdean/6.046/dp/.
http://ideone.com/j2TklH
Prints the Box Stack too!!!
int compare(const void* a, const void* b)
{
    return ((*(Box *)b).l)*((*(Box *)b).w) - ((*(Box *)a).l)*((*(Box *)a).w);
}

int maxBoxHeight(Box arr[], int n)
{
    Box rot[3*n];
    int temp;
    int r=0;

    for(int i=0; i<n; i++)
    {
        rot[r] = arr[i];
        r++;

        rot[r].h = arr[i].l;
        rot[r].l = max(arr[i].w, arr[i].h);
        rot[r].w = min(arr[i].w, arr[i].h);
        r++;

        rot[r].h = arr[i].w;
        rot[r].l = max(arr[i].l, arr[i].h);
        rot[r].w = min(arr[i].l, arr[i].h);
        r++;
    }

    n = 3*n;
    qsort(rot, n, sizeof(rot[0]), compare);

    int tab[n];
    int res[n];

    for(int i=0; i<n; i++)
        tab[i] = rot[i].h, res[i] = -1;

    for(int i=1; i<n; i++)
    {
        for(int j=0; j<i; j++)
        {
            if(rot[i].l < rot[j].l && rot[i].w < rot[j].w && tab[j] + rot[i].h > tab[i])
            {
                tab[i] = tab[j] + rot[i].h;
                res[i] = j;
            }
        }
    }

    int k=n-1;
    while(k != -1)
    {
        printf("%2d x %2d x %2d\n", rot[k].l, rot[k].w, rot[k].h);
        k = res[k];
    }

    return tab[n-1];

}
Crack Coding Interview: [CC150v5] 9.10 Stack Up the Boxes
A little bit different
http://www.shuatiblog.com/blog/2014/09/17/stack-up-boxes/
You have a stack of n boxes, with widths w., heights h, and depths d. The boxes can only be stacked on top of one another if each box is strictly larger than the box above it in width, height, and depth.

Implement a method to build the tallest stack possible, where the height of a stack is the sum of the heights of each box.

Because here it requires strictly larger => so we don't need do backtrack: remove it from box arrays then add back later.
http://www.shuatiblog.com/blog/2014/09/17/stack-up-boxes/
we keeps 2 DP arrays
public static ArrayList<Box> createStack(Box[] boxes) {
    ArrayList<Box> ans = new ArrayList<Box>();
    int len = boxes.length;
    int[] heights = new int[len];
    int[] preMap = new int[len];
    int maxIndex = 0;

    // start DP
    for (int i = 0; i < len; i++) {
        heights[i] = boxes[i].height;
        preMap[i] = -1;
        for (int j = 0; j < i; j++) {
            if (boxes[j].canBeAbove(boxes[i])) {
                int newHeight = heights[j] + boxes[i].height;
                if (newHeight > heights[i]) {
                    heights[i] = newHeight;
                    preMap[i] = j;
                }
            }
        }
        // now updated maxIndex
        if (heights[i] > heights[maxIndex]) {
            maxIndex = i;
        }
    }

    // print from maxIndex all the way backwards
    while (maxIndex != -1) {
        ans.add(boxes[maxIndex]);
        // the print order is reversed, so...
        maxIndex = preMap[maxIndex];
    }
    return ans;
}


http://www.cnblogs.com/grandyang/p/4847695.html
我们也可以用哈希表来优化,保存我们之前算过的最优解,那么在递归调用需要相同的结果时,就可以直接从哈希表中调用
https://github.com/wzhishen/cracking-the-coding-interview/blob/master/src/chap09/Q10.java
//    You have a stack of n boxes, with widths w, heights h and depths d. The boxes
//    cannot be rotated and can only be stacked on top of one another if each box in the
//    stack is strictly larger than the box above it in width, height, and depth. Implement
//    a method to build the tallest stack possible, where the height of a stack is the sum of
//    the heights of each box.
static ArrayList<Box> buildTallestStack(ArrayList<Box> boxes, Box bottom) {
    ArrayList<Box> maxStack = null;
    int maxHeight = 0;
    for (Box b : boxes) {
        if (b.canPlaceAbove(bottom)) {
            ArrayList<Box> newStack = buildTallestStack(boxes, b);
            int newHeight = stackHeight(newStack);
            if (newHeight > maxHeight) {
                maxHeight = newHeight;
                maxStack = newStack;
            }
        }
    }
    if (maxStack == null) maxStack = new ArrayList<Box>();
    if (bottom != null) maxStack.add(0, bottom);
    return maxStack;
}

static ArrayList<Box> buildTallestStack(ArrayList<Box> boxes) {
    if (boxes == null) return null;
    return buildTallestStack(boxes, null);
}

static ArrayList<Box> buildTallestStackDP(ArrayList<Box> boxes, Box bottom, 
        HashMap<Box, ArrayList<Box>> cache) {
    if (cache.containsKey(bottom))
        return cache.get(bottom);
    
    ArrayList<Box> maxStack = null;
    int maxHeight = 0;
    for (Box b : boxes) {
        if (b.canPlaceAbove(bottom)) {
            ArrayList<Box> newStack = buildTallestStackDP(boxes, b, cache);
            int newHeight = stackHeight(newStack);
            if (newHeight > maxHeight) {
                maxHeight = newHeight;
                maxStack = newStack;
            }
        }
    }
    if (maxStack == null) maxStack = new ArrayList<Box>();
    if (bottom != null) maxStack.add(0, bottom);
    cache.put(bottom, maxStack);
    return maxStack;
}

static ArrayList<Box> buildTallestStackDP(ArrayList<Box> boxes) {
    if (boxes == null) return null;
    return buildTallestStackDP(boxes, null, new HashMap<Box, ArrayList<Box>>());
}
private static int stackHeight(ArrayList<Box> boxes) {
    int height = 0;
    for (Box b : boxes) {
        height += b.height;
    }
    return height;
}

static class Box {
    int width; int length; int height;
    public Box(int w, int l, int h) {width=w;length=l;height=h;}
    
    boolean canPlaceAbove(Box b) {
        return b == null ||
                (this.width < b.width &&
                this.length < b.length &&
                this.height < b.height);
    }

}
https://ziliangzhu.wordpress.com/2013/11/16/you-have-a-stack-of-n-boxes-with-widths-w-heights-l-and-depths-dr-the-boxes-cannot-be-rotated-and-can-only-be-stacked-on-top-of-one-another-if-each-box-in-the-stack-is-strictly-larger-than-the-bo/
public ArrayList<Box> getTallestBoxStack(Box[] boxes) {
 HashMap<Box, ArrayList<Box>> myHash = new HashMap<Box, ArrayList<Box>>();
 return getTallestBoxStack(myHash, boxes, null);
 }

private ArrayList<Box> getTallestBoxStack(
 HashMap<Box, ArrayList<Box>> myHash, Box[] boxes, Box currentBox) {
// Base and Recursion
// Check hashmap
if (currentBox != null && myHash.containsKey(currentBox)) {
return myHash.get(currentBox);
} else {
// Temporary instance
ArrayList<Box> previous = null;
double previousHighestHeight = 0;

// To return value
ArrayList<Box> previousFinal = new ArrayList<Box>();

// Recursion
for (int i = 0; i < boxes.length; i++) {
// If any box is smaller than current box
if (boxes[i].isSmallerThan(currentBox)) {
previous = getTallestBoxStack(myHash, boxes, boxes[i]);
// Compare height and update the final previous
double previousHeight = getStackHeight(previous);
if (previousHeight > previousHighestHeight) {
// update height record
previousHighestHeight = previousHeight;
previousFinal = previous;
}
}
}

// Ready to return
if (currentBox != null){
previousFinal.add(currentBox);
// update hashmap
myHash.put(currentBox, previousFinal);
}

// return a deep copy
return new ArrayList<Box>(previousFinal);
}
 }

private double getStackHeight(ArrayList<Box> boxes) {
 double returnVal = 0;
 for (Box i : boxes) {
 returnVal += i.height;
 }
 return returnVal;
 }
}
https://richdalgo.wordpress.com/2014/12/31/cc150-recursion-and-dp/
https://gist.github.com/ivycheung1208/9b0c648aacdb1d52ae11
http://codinginterview.net/post/you-have-a-stack-of-n-boxes-with-widths-w-heights-h-and-depths-d-implement-a-method-to-build-the-tallest-stack-possible
Understanding k-Dimensions
You are given n boxes each of k dimensions to figure out the maximum number of box-in-box chains (called nested boxes) you can form.

For a box to fit, the value of every dimension must be smaller than the pair-wise association of the other box. What his means is box (1,2,3) fits into box (2,3,4) because each dimension is 1 unit smaller. To easily determine this, we can simply sort the box's dimensions and compare each value pairwise. Now we can define the box object.

Given n boxes with length and width. A box with smaller length and smaller width can be put on a box with larger length and larger width.
Each box height is 1. Find the tallest box that they can put together. In general, we can build the box with m-dimension.
For example, if we have:
boxes = {
{0, 0},
{1, 2},
{1, 1},
{3, 4},
{4, 3},
{4, 4},
{3, 3} };
A longest possible combination is: (4, 4)->(3, 4)->(3, 3)->(1, 2)->(1, 1)->(0, 0). So tallest height is 6.
For n boxes, we do comparison between each box. If box[j] can be put on box[i], then we put an edge from box[i]->box[j].
In this way, we build a graph among boxes. Gathering all the boxes which doesn’t has parent, we use BFS to iterate.
The max number of iteration will be the result.
Assume a graph is like below, we can see the total iteration starting from v1, v2 to the end is 4.
public static int getTallestBox(int[][] boxes) {
    assert boxes!=null && boxes.length>0 && boxes[0]!=null && boxes[0].length>0;
    Queue<Node> mainQueue = initialStack(boxes);
    Queue<Node> auxQueue = new ArrayDeque<Node>();
    int tall = 0;
    while(!mainQueue.isEmpty()) {
        tall++;
        while (!mainQueue.isEmpty()) {
            Node node = mainQueue.remove();
            for(Node curr:node.neighbor) {
                auxQueue.add(curr);
            }
        }
        Queue<Node> tmp = mainQueue;
        mainQueue = auxQueue;
        auxQueue = tmp;
    }
    return tall;
}

public static Queue<Node> initialStack(int[][] boxes) {
    boolean[] nonHeads = new boolean[boxes.length];
    Node[] nodes = new Node[boxes.length];
    Queue<Node> heads = new ArrayDeque<Node>();
    for(int i=0; i<nodes.length; i++) {
        nodes[i] = new Node(boxes[i]);
    }
    // build graph
    for(int i=0; i<nodes.length-1; i++) {
        for(int j=i+1; j<nodes.length; j++) {
            int compare = compare(nodes[i].box, nodes[j].box);
            switch (compare) {
                case -1:
                    nodes[j].addNeighbor(nodes[i]);
                    nonHeads[i] = true;
                    break;
                case 1:
                    nodes[i].addNeighbor(nodes[j]);
                    nonHeads[j] = true;
                    break;
                case 0:
                    break;
            }// switch
        }// for
    }
    // mark head nodes who has out-going edge.
    for(int i=0; i<nonHeads.length; i++) {
        if (!nonHeads[i])
            heads.add(nodes[i]);
    }
    return heads;
}

/*
Return 1 when arr1>arr2.
Return -1 when arr1<arr2.
Return 0 when arr1 can't compare to arr2.
 */
public static int compare(int[] arr1, int[] arr2) {
    boolean larger = true;
    boolean smaller = true;
    for(int i=0; i<arr1.length; i++) {
        if(arr1[i]<arr2[i])
            larger = false;
        else if(arr1[i]>arr2[i])
            smaller = false;
        else if(!larger && !smaller)
            return 0;
    }
    if(larger)
        return 1;
    else if(smaller)
        return -1;
    return 0;
}

public static class Node {
    public int[] box;
    public HashSet<Node> neighbor = new HashSet<Node>();
    public Node(int[] box) {
        this.box = box;
    }
    public void addNeighbor(Node node) {
        neighbor.add(node);
    }
}
public static void main(String[] args) {
    int[] arr1 = {1, 4, 5};
    int[] arr2 = {1, 3, 5};
    int[][] boxes = {
            {0, 0},
            {1, 2},
            {1, 1},
            {3, 4},
            {4, 3},
            {4, 4},
            {3, 3}
    };
    System.out.println(getTallestBox(boxes));
}
Read full article from Dynamic Programming | Set 22 (Box Stacking Problem) | GeeksforGeeks

Labels

LeetCode (1432) GeeksforGeeks (1122) LeetCode - Review (1067) Review (882) Algorithm (668) to-do (609) Classic Algorithm (270) Google Interview (237) Classic Interview (222) Dynamic Programming (220) DP (186) Bit Algorithms (145) POJ (141) Math (137) Tree (132) LeetCode - Phone (129) EPI (122) Cracking Coding Interview (119) DFS (115) Difficult Algorithm (115) Lintcode (115) Different Solutions (110) Smart Algorithm (104) Binary Search (96) BFS (91) HackerRank (90) Binary Tree (86) Hard (79) Two Pointers (78) Stack (76) Company-Facebook (75) BST (72) Graph Algorithm (72) Time Complexity (69) Greedy Algorithm (68) Interval (63) Company - Google (62) Geometry Algorithm (61) Interview Corner (61) LeetCode - Extended (61) Union-Find (60) Trie (58) Advanced Data Structure (56) List (56) Priority Queue (53) Codility (52) ComProGuide (50) LeetCode Hard (50) Matrix (50) Bisection (48) Segment Tree (48) Sliding Window (48) USACO (46) Space Optimization (45) Company-Airbnb (41) Greedy (41) Mathematical Algorithm (41) Tree - Post-Order (41) ACM-ICPC (40) Algorithm Interview (40) Data Structure Design (40) Graph (40) Backtracking (39) Data Structure (39) Jobdu (39) Random (39) Codeforces (38) Knapsack (38) LeetCode - DP (38) Recursive Algorithm (38) String Algorithm (38) TopCoder (38) Sort (37) Introduction to Algorithms (36) Pre-Sort (36) Beauty of Programming (35) Must Known (34) Binary Search Tree (33) Follow Up (33) prismoskills (33) Palindrome (32) Permutation (31) Array (30) Google Code Jam (30) HDU (30) Array O(N) (29) Logic Thinking (29) Monotonic Stack (29) Puzzles (29) Code - Detail (27) Company-Zenefits (27) Microsoft 100 - July (27) Queue (27) Binary Indexed Trees (26) TreeMap (26) to-do-must (26) 1point3acres (25) GeeksQuiz (25) Merge Sort (25) Reverse Thinking (25) hihocoder (25) Company - LinkedIn (24) Hash (24) High Frequency (24) Summary (24) Divide and Conquer (23) Proof (23) Game Theory (22) Topological Sort (22) Lintcode - Review (21) Tree - Modification (21) Algorithm Game (20) CareerCup (20) Company - Twitter (20) DFS + Review (20) DP - Relation (20) Brain Teaser (19) DP - Tree (19) Left and Right Array (19) O(N) (19) Sweep Line (19) UVA (19) DP - Bit Masking (18) LeetCode - Thinking (18) KMP (17) LeetCode - TODO (17) Probabilities (17) Simulation (17) String Search (17) Codercareer (16) Company-Uber (16) Iterator (16) Number (16) O(1) Space (16) Shortest Path (16) itint5 (16) DFS+Cache (15) Dijkstra (15) Euclidean GCD (15) Heap (15) LeetCode - Hard (15) Majority (15) Number Theory (15) Rolling Hash (15) Tree Traversal (15) Brute Force (14) Bucket Sort (14) DP - Knapsack (14) DP - Probability (14) Difficult (14) Fast Power Algorithm (14) Pattern (14) Prefix Sum (14) TreeSet (14) Algorithm Videos (13) Amazon Interview (13) Basic Algorithm (13) Codechef (13) Combination (13) Computational Geometry (13) DP - Digit (13) LCA (13) LeetCode - DFS (13) Linked List (13) Long Increasing Sequence(LIS) (13) Math-Divisible (13) Reservoir Sampling (13) mitbbs (13) Algorithm - How To (12) Company - Microsoft (12) DP - Interval (12) DP - Multiple Relation (12) DP - Relation Optimization (12) LeetCode - Classic (12) Level Order Traversal (12) Prime (12) Pruning (12) Reconstruct Tree (12) Thinking (12) X Sum (12) AOJ (11) Bit Mask (11) Company-Snapchat (11) DP - Space Optimization (11) Dequeue (11) Graph DFS (11) MinMax (11) Miscs (11) Princeton (11) Quick Sort (11) Stack - Tree (11) 尺取法 (11) 挑战程序设计竞赛 (11) Coin Change (10) DFS+Backtracking (10) Facebook Hacker Cup (10) Fast Slow Pointers (10) HackerRank Easy (10) Interval Tree (10) Limited Range (10) Matrix - Traverse (10) Monotone Queue (10) SPOJ (10) Starting Point (10) States (10) Stock (10) Theory (10) Tutorialhorizon (10) Kadane - Extended (9) Mathblog (9) Max-Min Flow (9) Maze (9) Median (9) O(32N) (9) Quick Select (9) Stack Overflow (9) System Design (9) Tree - Conversion (9) Use XOR (9) Book Notes (8) Company-Amazon (8) DFS+BFS (8) DP - States (8) Expression (8) Longest Common Subsequence(LCS) (8) One Pass (8) Quadtrees (8) Traversal Once (8) Trie - Suffix (8) 穷竭搜索 (8) Algorithm Problem List (7) All Sub (7) Catalan Number (7) Cycle (7) DP - Cases (7) Facebook Interview (7) Fibonacci Numbers (7) Flood fill (7) Game Nim (7) Graph BFS (7) HackerRank Difficult (7) Hackerearth (7) Inversion (7) Kadane’s Algorithm (7) Manacher (7) Morris Traversal (7) Multiple Data Structures (7) Normalized Key (7) O(XN) (7) Radix Sort (7) Recursion (7) Sampling (7) Suffix Array (7) Tech-Queries (7) Tree - Serialization (7) Tree DP (7) Trie - Bit (7) 蓝桥杯 (7) Algorithm - Brain Teaser (6) BFS - Priority Queue (6) BFS - Unusual (6) Classic Data Structure Impl (6) DP - 2D (6) DP - Monotone Queue (6) DP - Unusual (6) DP-Space Optimization (6) Dutch Flag (6) How To (6) Interviewstreet (6) Knapsack - MultiplePack (6) Local MinMax (6) MST (6) Minimum Spanning Tree (6) Number - Reach (6) Parentheses (6) Pre-Sum (6) Probability (6) Programming Pearls (6) Rabin-Karp (6) Reverse (6) Scan from right (6) Schedule (6) Stream (6) Subset Sum (6) TSP (6) Xpost (6) n00tc0d3r (6) reddit (6) AI (5) Abbreviation (5) Anagram (5) Art Of Programming-July (5) Assumption (5) Bellman Ford (5) Big Data (5) Code - Solid (5) Code Kata (5) Codility-lessons (5) Coding (5) Company - WMware (5) Convex Hull (5) Crazyforcode (5) DFS - Multiple (5) DFS+DP (5) DP - Multi-Dimension (5) DP-Multiple Relation (5) Eulerian Cycle (5) Graph - Unusual (5) Graph Cycle (5) Hash Strategy (5) Immutability (5) Java (5) LogN (5) Manhattan Distance (5) Matrix Chain Multiplication (5) N Queens (5) Pre-Sort: Index (5) Quick Partition (5) Quora (5) Randomized Algorithms (5) Resources (5) Robot (5) SPFA(Shortest Path Faster Algorithm) (5) Shuffle (5) Sieve of Eratosthenes (5) Strongly Connected Components (5) Subarray Sum (5) Sudoku (5) Suffix Tree (5) Swap (5) Threaded (5) Tree - Creation (5) Warshall Floyd (5) Word Search (5) jiuzhang (5)

Popular Posts