views:

783

answers:

4

I found this famous dp problem in many places, but I can not figure out how to solve.

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.

This problem seems too complicated for me to figure out the steps. As it is 3D, I get three sequence of height, width and depth. But as it is possible to exchange 3 dimension the problem becomes more complicated for me. So please someone explain the steps to solve the problem when there is no swapping and then how to do it when swapping. I became tired about the problem. So please, please someone explain the solution easy way.

A: 

I suggest you create a tree (or some sort of tree structure) and parse it with depth search, calculating the max height from the individual vertical "height" (depening on rotation) values.

This (I think this is the basic approach).

Details over details:

The Tree root should be the floor, where any cube fits onto. From there you just create the child nodes of possible next (boxes that can be placed in a certain rotation ontop of the current box) boxes. Recursivly do that for each box and rotation.

When the tree is build, go through it and calc the total tower heigth from floor to a leaf of the tree.

penguinpower
That's exponential (factorial even) in the number of boxes. He said he's specifically looking for a dp (dynamic programming) solution.
Peter Alexander
Missread... my fault
penguinpower
+6  A: 

I think you can solve this using the dynamic programming longest increasing subsequence algorithm: http://www.algorithmist.com/index.php/Longest_Increasing_Subsequence

Accounting for the rotations is easy enough: for every tower all you have to check is what happens if you use its height as the length of the base and its width as the height and what happens if you use it in the natural way. For example:

=============
=           =
=           =
=           = L
=     H     =
=           =
=           =
=============   
      W

Becomes something like (yeah, I know it looks nothing like it should, just follow the notations):

==================
=                =
=                =  
=       W        = L
=                =
=                =
==================
        H

Then just apply the DP LIS algorithm to the get the maximum height.

The adapted recurrence is: D[i] = maximum height we can obtain if the last tower must be i.

D[1] = h(1);
D[i] = h(i) + max(D[j] | j <= i and we can put tower i on tower j for at least one rotation of tower i) or simply h(i) if nu such D[j] exists.

Answer is the max element of D.
IVlad
Shouldn't D[1] = h(1)?
Peter Alexander
here i get 3-sequence of height,width and length.so how will i find longest increasing sequence??is there sorting needed??plz dont feel bother to ans.
russell
@Poita_: true, I updated my post. Thank you :).@russell: I'm not sure sorting is needed, although it might help as an optimization. You can just try all possible rotations - I think some of them repeat, but you can just try all 3! = 6 permutations of (height, width, length) for a tower i when trying to put it on top of a tower j and see if a valid one works. If one of them works, great, if not, try another j. Don't hesitate to post back if you have more questions :).Optimizations should be possible - there's no point of trying all 6 permutations, but it's the easiest for a first solution.
IVlad
Just to clarify my previous comment: not all permutations will be valid, you only try the valid ones of course. I'll let you figure out which ones aren't valid. Basically, saying "try all rotations" is the right way, saying "all valid permutations" is a bit misleading, sorry about that.
IVlad
what if the 1st element has the smallest width and depth of them all? shouldn't it's height be added to some other tower, although no other block fits on top of it?
Amir Arad
True, you must sort like you said and then apply the recurrence.
IVlad
+1  A: 

The stack can be regarded as a sequence of x,y,z triplets (x,y being the 2D plane, and z the height), where x(i) > x(i+1) and y(i) > y(i+1). The goal is to maximize the sum of z picking the triplets from the set of available triplets - each triplet being one type of box in a particular orientation. It is pretty easy to see that enforcing the constraint x > y doesn't reduce the solution space. So each box generates 3 triplets, having each of w,h,d as the z coordinate.

If you regard the triplets as a directed acyclic graph where edges of length z exist between two triplets when the x,y constraints are satisfied between them, then the problem is of finding the longest path through that graph.

Ants Aasma
cool . what if one is allowed to use only one box of each type
hotadvice
+1  A: 

Let's first try to solve this problem in 2-D:

say you have rectangles with X's and Y's, and the question is similar (highest tower, but this time you only have to worry about one base dimension).
so first, you go over the whole collection, duplicating each rectangle by rotating it 90 degrees (swapping X and Y), except for squares (where X(1)=X(2) && Y(1)=Y(2)). this represents all possible variations.
then you sort them by their X side, from largest to smallest. in case of duplicate X value, you remove the one with the lower Y value.

same principle applied in the 3-D scenario, only now you DONT just multiply the collection's size by 6 (every possible variants of the W, H, D) but rather by 2. you do this by dismissing all variations where the width is lower than the depth ( so for each i, W(i)>=D(i)), and then dismissing the variation where the height is not the highest nor the lowest of the three dimensions (because the other two variations can go one on top of the other and this one can't join in). again, you also dismiss duplications (where W(1)=W(2) && H(1)=H(2) && D(1)=D(2)).
Then you should sort by width, only this time you don;t throw away variations with the same width (because one may fit in a tower that another may not) then you can use the LIS algorithm as described above by @IVlad :

D[1] = h(1);
D[i] = h(i) + max(D[j] | j <= i and we can put tower i on tower j) or simply h(i) if no such D[j] exists.

the trick was, you know that the width is the longest of the two, so you know the first element will not fit on top of any later element.

Amir Arad