forked from klw910/cracking-the-coding-interview
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbox stacking
146 lines (128 loc) · 4.85 KB
/
box stacking
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
package com.interview.dynamic;
import java.util.Arrays;
/**
* Date 05/09/2015
* @author tusroy
*
* Given different dimensions and unlimited supply of boxes for each dimension, stack boxes
* on top of each other such that it has maximum height but with caveat that length and width
* of box on top should be strictly less than length and width of box under it. You can
* rotate boxes as you like.
*
* 1) Create all rotations of boxes such that length is always greater or equal to width
* 2) Sort boxes by base area in non increasing order (length * width). This is because box
* with more area will never ever go on top of box with less area.
* 3) Take T[] and result[] array of same size as total boxes after all rotations are done
* 4) Apply longest increasing subsequence type of algorithm to get max height.
*
* If n number of dimensions are given total boxes after rotation will be 3n.
* So space complexity is O(n)
* Time complexity - O(nlogn) to sort boxes. O(n^2) to apply DP on it So really O(n^2)
*
* References
* http://www.geeksforgeeks.org/dynamic-programming-set-21-box-stacking-problem/
* http://people.cs.clemson.edu/~bcdean/dp_practice/
*/
public class BoxStacking {
public int maxHeight(Dimension[] input) {
//get all rotations of box dimension.
//e.g if dimension is 1,2,3 rotations will be 2,1,3 3,2,1 3,1,2 . Here length is always greater
//or equal to width and we can do that without loss of generality.
Dimension[] allRotationInput = new Dimension[input.length * 3];
createAllRotation(input, allRotationInput);
//sort these boxes in non increasing order by their base area.(length X width)
Arrays.sort(allRotationInput);
//apply longest increasing subsequence kind of algorithm on these sorted boxes.
int T[] = new int[allRotationInput.length];
int result[] = new int[allRotationInput.length];
for (int i = 0; i < T.length; i++) {
T[i] = allRotationInput[i].height;
result[i] = i;
}
for (int i = 1; i < T.length; i++) {
for (int j = 0; j < i; j++) {
if (allRotationInput[i].length < allRotationInput[j].length
&& allRotationInput[i].width < allRotationInput[j].width) {
if( T[j] + allRotationInput[i].height > T[i]){
T[i] = T[j] + allRotationInput[i].height;
result[i] = j;
}
}
}
}
//find max in T[] and that will be our max height.
//Result can also be found using result[] array.
int max = Integer.MIN_VALUE;
for(int i=0; i < T.length; i++){
if(T[i] > max){
max = T[i];
}
}
return max;
}
//create all rotations of boxes, always keeping length greater or equal to width
private void createAllRotation(Dimension[] input,
Dimension[] allRotationInput) {
int index = 0;
for (int i = 0; i < input.length; i++) {
allRotationInput[index++] = Dimension.createDimension(
input[i].height, input[i].length, input[i].width);
allRotationInput[index++] = Dimension.createDimension(
input[i].length, input[i].height, input[i].width);
allRotationInput[index++] = Dimension.createDimension(
input[i].width, input[i].length, input[i].height);
}
}
public static void main(String args[]) {
BoxStacking bs = new BoxStacking();
Dimension input[] = { new Dimension(3, 2, 5), new Dimension(1, 2, 4) };
int maxHeight = bs.maxHeight(input);
System.out.println("Max height is " + maxHeight);
assert 11 == maxHeight;
}
}
/**
* Utility class to hold dimensions
* @author tusroy
*
*/
class Dimension implements Comparable<Dimension> {
int height;
int length;
int width;
Dimension(int height, int length, int width) {
this.height = height;
this.length = length;
this.width = width;
}
Dimension() {
}
static Dimension createDimension(int height, int side1, int side2) {
Dimension d = new Dimension();
d.height = height;
if (side1 >= side2) {
d.length = side1;
d.width = side2;
} else {
d.length = side2;
d.width = side1;
}
return d;
}
/**
* Sorts by base area(length X width)
*/
@Override
public int compareTo(Dimension d) {
if (this.length * this.width >= d.length * d.width) {
return -1;
} else {
return 1;
}
}
@Override
public String toString() {
return "Dimension [height=" + height + ", length=" + length
+ ", width=" + width + "]";
}
}