
Input: n =2, m =3Output: 3Explanation: 3 squares are necessary to cover the rectangle.2(squares of 1x1)1(square of 2x2)
Try to fill the rectangle greedily with the largest possible square at each step, backtracking and pruning when the current path cannot improve the best answer found so far.
Use DFS/backtracking. At each step, find the first empty cell, try all possible square sizes, fill, recurse, and backtrack. Prune if the current count exceeds the best found.
#include<vector>#include<algorithm>usingnamespace std;
classSolution {
public:int res = INT_MAX;
inttilingRectangle(int n, int m) {
vector<vector<int>> rect(n, vector<int>(m));
dfs(rect, 0);
return res;
}
voiddfs(vector<vector<int>>& rect, int cnt) {
int n = rect.size(), m = rect[0].size();
if (cnt >= res) return;
int x =-1, y =-1;
for (int i =0; i < n; ++i) {
for (int j =0; j < m; ++j) {
if (rect[i][j] ==0) {
x = i; y = j;
goto found;
}
}
}
res = min(res, cnt);
return;
found:
int maxLen = min(n - x, m - y);
for (int k = maxLen; k >=1; --k) {
bool canFill = true;
for (int i =0; i < k && canFill; ++i)
for (int j =0; j < k && canFill; ++j)
if (rect[x + i][y + j]) canFill = false;
if (!canFill) continue;
for (int i =0; i < k; ++i)
for (int j =0; j < k; ++j)
rect[x + i][y + j] =1;
dfs(rect, cnt +1);
for (int i =0; i < k; ++i)
for (int j =0; j < k; ++j)
rect[x + i][y + j] =0;
}
}
};
import java.util.*;
publicclassSolution {
privateint res = Integer.MAX_VALUE;
publicinttilingRectangle(int n, int m) {
int[][] rect =newint[n][m];
dfs(rect, 0);
return res;
}
privatevoiddfs(int[][] rect, int cnt) {
int n = rect.length, m = rect[0].length;
if (cnt >= res) return;
int x =-1, y =-1;
outer:
for (int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) {
if (rect[i][j]== 0) {
x = i; y = j;
break outer;
}
}
}
if (x ==-1) {
res = Math.min(res, cnt);
return;
}
int maxLen = Math.min(n - x, m - y);
for (int k = maxLen; k >= 1; --k) {
boolean canFill =true;
for (int i = 0; i < k && canFill; ++i)
for (int j = 0; j < k && canFill; ++j)
if (rect[x + i][y + j]!= 0) canFill =false;
if (!canFill) continue;
for (int i = 0; i < k; ++i)
for (int j = 0; j < k; ++j)
rect[x + i][y + j]= 1;
dfs(rect, cnt + 1);
for (int i = 0; i < k; ++i)
for (int j = 0; j < k; ++j)
rect[x + i][y + j]= 0;
}
}
}
classSolution:
deftilingRectangle(self, n: int, m: int) -> int:
self.res = n * m
rect = [[0] * m for _ in range(n)]
defdfs(cnt):
if cnt >= self.res:
returnfor i in range(n):
for j in range(m):
if rect[i][j] ==0:
x, y = i, j
breakelse:
continuebreakelse:
self.res = min(self.res, cnt)
return max_len = min(n - x, m - y)
for k in range(max_len, 0, -1):
can_fill =Truefor dx in range(k):
for dy in range(k):
if rect[x + dx][y + dy]:
can_fill =Falsebreakifnot can_fill:
breakifnot can_fill:
continuefor dx in range(k):
for dy in range(k):
rect[x + dx][y + dy] =1 dfs(cnt +1)
for dx in range(k):
for dy in range(k):
rect[x + dx][y + dy] =0 dfs(0)
return self.res
impl Solution {
pubfntiling_rectangle(n: i32, m: i32) -> i32 {
fndfs(rect: &mut Vec<Vec<i32>>, cnt: i32, res: &muti32) {
let n = rect.len();
let m = rect[0].len();
if cnt >=*res { return; }
letmut x = None;
letmut y = None;
'outer: for i in0..n {
for j in0..m {
if rect[i][j] ==0 {
x = Some(i); y = Some(j);
break 'outer;
}
}
}
if x.is_none() {
*res = cnt.min(*res);
return;
}
let x = x.unwrap();
let y = y.unwrap();
let max_len = n.min(m).min(n - x).min(m - y);
for k in (1..=max_len).rev() {
letmut can_fill =true;
'check: for dx in0..k {
for dy in0..k {
if rect[x + dx][y + dy] !=0 {
can_fill =false;
break 'check;
}
}
}
if!can_fill { continue; }
for dx in0..k {
for dy in0..k {
rect[x + dx][y + dy] =1;
}
}
dfs(rect, cnt +1, res);
for dx in0..k {
for dy in0..k {
rect[x + dx][y + dy] =0;
}
}
}
}
let n = n asusize;
let m = m asusize;
letmut rect =vec![vec![0; m]; n];
letmut res = (n * m) asi32;
dfs(&mut rect, 0, &mut res);
res
}
}