Formatted question description: https://leetcode.ca/all/1240.html
1240. Tiling a Rectangle with the Fewest Squares
Level
Hard
Description
Given a rectangle of size n
x m
, find the minimum number of integer-sided squares that tile the rectangle.
Example 1:
Input: n = 2, m = 3
Output: 3
Explanation: 3 squares are necessary to cover the rectangle.
2 (squares of 1x1)
1 (square of 2x2)
Example 2:
Input: n = 5, m = 8
Output: 5
Example 3:
Input: n = 11, m = 13
Output: 6
Constraints:
1 <= n <= 13
1 <= m <= 13
Solution
Use dynamic programming. Create a 2D array dp
of n + 1
rows and m + 1
columns, where dp[i][j]
represents the minimum number of squares required to tile the i * j
rectangle.
Obviously, if i == j
, dp[i][j] = 1
. Otherwise, the rectangle can be split by a horizontal line or a vertical line, which leads to two smaller rectangles, or a square may be put in the middle. For each case, calculate the minimum number of squares needed.
Finally, return dp[n][m]
.
class Solution {
public int tilingRectangle(int n, int m) {
int[][] dp = new int[n + 1][m + 1];
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
if (i == j)
dp[i][j] = 1;
else {
dp[i][j] = Integer.MAX_VALUE;
int rowStart = 1, rowEnd = i / 2;
for (int row = rowStart; row <= rowEnd; row++)
dp[i][j] = Math.min(dp[i][j], dp[row][j] + dp[i - row][j]);
int columnStart = 1, columnEnd = j / 2;
for (int column = columnStart; column <= columnEnd; column++)
dp[i][j] = Math.min(dp[i][j], dp[i][column] + dp[i][j - column]);
for (int row = 1; row <= i; row++) {
for (int column = 1; column <= j; column++) {
for (int side = Math.min(row, column) - 1; side > 0; side--)
dp[i][j] = Math.min(dp[i][j], 1 + dp[row - side][column] + dp[i - row + side][column - side] + dp[i - row][j - column + side] + dp[row][j - column]);
}
}
}
}
}
return dp[n][m];
}
}