LC 1240 Tiling a Rectangle with the Fewest Squares
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
思考过程:一开始思考,往trick方向想,觉得要不要有特殊的算法,先取最小边,然后填上最小边长的正方形等等。后来发现,想复杂了。这道题只需要暴力枚举,注意剪枝和优化即可。
class Solution {
public:
int tilingRectangle(int n, int m) {
int size = max(n, m);
vector<int> height(size, 0);
int total = 0;
dfs(total, height, min(n, m));
return global_total_min_;
}
private:
void dfs(int total, vector<int> height, const int target_height) {
if (total > global_total_min_) {
return;
}
int smallest_index = -1;
for (int i = 0; i < height.size(); ++i) {
if (height.at(i) == target_height) {
continue;
}
if (smallest_index != -1) {
smallest_index = height.at(smallest_index) > height.at(i) ? i : smallest_index;
} else {
smallest_index = i;
}
}
if (smallest_index != -1) {
// continue to fullfill
int local_start = smallest_index;
int local_end = smallest_index + 1;
while (local_end != height.size() &&
height.at(local_end) == height.at(local_start)) {
++local_end;
}
// 错误1:忘了回溯需要回复原样
vector<int> backup_height = height;
for (; local_end != local_start; --local_end) {
int next_square_size = min(local_end - local_start,
target_height - height.at(smallest_index));
height = backup_height;
// 错误2: 忘了这个方形是等长,终止条件没设对
for (int i = local_start; i < local_start + next_square_size; ++i) {
// 错误3:忘了是叠加,不是重设;
height[i] += next_square_size;
}
long pattern = height.at(0);
// calculate the current pattern
for (int i = 1; i < height.size(); ++i) {
pattern = (pattern * target_height) + height.at(i);
}
if (pattern_met_min_.find(pattern) != pattern_met_min_.end() &&
pattern_met_min_.at(pattern) < total) {
// 错误4,不是遇到重复的pattern就返回,还要对比局部最优
// met before, don't need to do again
return;
}
pattern_met_min_[pattern] = total;
dfs(total + 1, height, target_height);
}
} else {
// a full status
global_total_min_ = min(total, global_total_min_);
}
}
unordered_map<long, int> pattern_met_min_;
int global_total_min_ = INT_MAX;
};