I need to find the cuboid with the greatest volume, contained within a 2D-heightmap.
The heightmap is an array of size w*d
where w
is width, h
is height and d
is depth.
In C, this would look along the lines of:
unsigned heightmap[w][d]; // all values are <= h
I already know that there is a naive algorithm which can solve this with O(w*d*h)
complexity.
However, I suspect that there is a more optimal method out there.
It works as follows, in pythonic pseudocode:
resultRectangle = None
resultHeight = None
resultVolume = -1
# iterate over all heights
for loopHeight in range(0, h):
# create a 2D bitmap from our heightmap where a 1 represents a height >= loopHeight
bool bitmap[w][d]
for x in range(0, w):
for y in range(0, d):
bitmap[x][y] = heightmap[x][y] >= loopHeight
# obtain the greatest-volume cuboid at this particular height
maxRectangle = maxRectangleInBitmap(bitmap)
volume = maxRectangle.area() * loopHeight
# compare it to our current maximum and replace it if we found a greater cuboid
if volume > resultVolume:
resultHeight = loopHeight
resultVolume = volume
resultRectangle = maxRectangle
resultCuboid = resultRectangle.withHeight(resultHeight)
Finding the greatest area of all 1
in a rectangle is a known problem with O(1)
complexity per pixel or O(w*d)
in our case.
The total complexity of the naive approach is thus O(w*h*d)
.
So as I already stated, I was wondering if we can beat this complexity.
Perhaps we can get it down to O(w*d * log(h))
by searching through heights more intelligently instead of "brute-forcing" all of them.
The answer to this question Find largest cuboid containing only 1's in an NxNxN binary array by Evgeny Kluev seems to take a similar approach, but it falsely(?) assumes that the volumes which we would find at these heights form a unimodal function. If this was the case, we could use Golden Section Search to choose heights more intelligently, but I don't think we can.