-2

The problem states that I have a big rectangle, with dimension L and W, and unlimited number of identical small rectangles, with dimension l and w. L * W is guaranteed to be larger than l *w. So I want to find out the maximum number of small rectangles that I can put into the big rectangle, without overlapping. You can put the small rectangles in any orientation you like.

MathCs
  • 185
  • 1
  • 1
  • 10

1 Answers1

2

Axis Aligned

Rectangles fit best when they are tiled, with no space between. So, an outline of how to do it:

First, figure out how many fit if you just tile them in:

lFit = L / l // integer division for these, no remainder
wFit = W / w

You know that you can fit lFit * wFit rectangles inside if you stack them in the same orientation as the big rectangle. Check again with the other orientation, and choose the bigger one as your base.

Now you may have some space left over. That space is made up of rectangles. You can easily find the size of these from the previous step. Run it again for these smaller rectangles and add to the base number. Recurse until no more fit.

If no tiles will fit into the "remaining" smaller rectangle, it's time to check for tilted ones.

Diagonal

Once your tile does not fit axis-aligned into the rectangle, you need to tilt it. You can pack the most tiles in by tilting them just enough to fit in the longest box dimension, and placing it firmly against three walls. Then you try stacking more in below it.

Note: for all the math here, I'm using width as the "longest edge". If your rectangle/tile doesn't match, just flip the dimensions.

To figure out what the proper rotation angle is, you can use a trial/error binary search. I'm sure there's a more "mathy" way to do it, but this works well enough. The formula for the bounding width of a rotated rectangle is(angle in radians):

width = w * cos(angle) + h * sin(angle)

To do a trial/error, just loop it until you reach your tolerance:

// boxWidth, tileWidth, tileHeight
public static double getAngle(double bw, double tw, double th){
    double err = 10;
    double maxAngle = PI * 0.25; // 45 degrees, any more would be taller than wide
    double angle = maxAngle * 0.5; // start in the middle
    double angleDelta = angle * 0.5; // amount to change;
    count = 0;
    while(count++ < 100){
        double rotatedWidth = tw * Math.cos(angle) + th * Math.sin(angle);
        err = rotatedWidth - bw;
        if(Math.abs(err) < TOLERANCE){
            return angle;
        } else if(err < 0){
            angle -= angleDelta;
        } else {
            angle += angleDelta;
        }
        angleDelta *= 0.5;
    }
    return -1; // found no good angle in 100 attempts
}

Once you have the angle, you can use basic trig to figure out some other points:

  • Find the lowest y-point of the top edge of the tile where it will be placed. Call this y1
    • y1 = sin(angle) * tileWidth
  • Find the lowest point of the left edge of the tile. Call this y2
    • y2 = sin((PI * 0.5) - radians) * tileHeight
  • Each added tile will take up y2 vertical space, so the number that will fit is:
    • (boxHeight - y1) / y2

I created a small ideone.com example that you can play with, also. The code is rather ugly, but it works. For your example in comments(13x8, 14x1), it shows:

Rotated 26.23397827148437 degrees
y1 = 6.188525444904378
y2 = 0.8969959689614577
numTiles = 2
Geobits
  • 22,218
  • 6
  • 59
  • 103
  • Thanks for your answer, but I think it is not correct. As I have stated in the question, you need not necessarily put the small rectangles in the big one with strictly vertical and/or horizontal orientation. You can, in fact, put them however you like. An example would be, a big rectangle with dimension 13*8, and small one 14*1. You cannot fit even one, either horizontally or vertically. But you can fit two diagonally. – MathCs Sep 01 '13 at 20:16
  • Ah, I wasn't thinking diagonally. The only time that would be more efficient(I believe) is when one dimension of the smaller tiles is longer than both dimensions on the larger. Can that be handled as a separate case? – Geobits Sep 02 '13 at 15:16
  • Perhaps yes. It is exactly this case makes the problem challenging. – MathCs Sep 04 '13 at 10:37