铺瓷砖

发布时间 2023-06-08 01:41:52作者: 失控D大白兔

用边长为整数的正方形填充m×n的平面空间
返回最少的正方形

1. 纯纯的暴力

不存在某种贪心和动态规划可以完成状态的转移
只能暴力在每一个位置填充每一种情况的正方形

class Solution {
public:
    int ans;
    int tilingRectangle(int n, int m) {
        ans = max(n, m);//初始化一个上限,防止搜索空间过大
        vector<vector<bool>> rect(n, vector<bool>(m, false));//初始化覆盖空间
        dfs(0, 0, rect, 0);//从(0,0)处开始递归更新结果,初始正方形个数为0
        return ans;
    }

    void dfs(int x, int y, vector<vector<bool>> &rect, int cnt) {
        int n = rect.size(), m = rect[0].size();
        if (cnt >= ans)  return;//进行剪枝
        if (x >= n) {   //遍历完了所有行,进行更新
            ans = cnt; 
            return;
        }
        /* 检测下一行 */        
        if (y >= m) { //遍历完当前行,继续遍历下一行
            dfs(x + 1, 0, rect, cnt); 
            return;
        }        
        /* 如当前已经被覆盖,则直接尝试下一个位置 */
        if (rect[x][y]) {  
            dfs(x, y + 1, rect, cnt);
            return;
        }

        //做选择
        for (int k = min(n - x, m - y); k >= 1 && isAvailable(rect, x, y, k); k--) {//在当前位置由大到小填充正方形
            /* 将长度为 k 的正方形区域标记覆盖 */
            fillUp(rect, x, y, k, true);
            /* 跳过 k 个位置开始检测 */
            dfs(x, y + k, rect, cnt + 1); //递归到下一个位置
            fillUp(rect, x, y, k, false);//取消选择
        }
    }

    bool isAvailable(vector<vector<bool>> &rect, int x, int y, int k) {//检查对应区域是否已被填充
        for (int i = 0; i < k; i++) 
            for(int j = 0;j < k; j++)
                if(rect[x+i][y+j])  return false;
        return true;
    }

    void fillUp(vector<vector<bool>> &rect, int x, int y, int k, bool val) {
        for (int i = 0; i < k; i++) 
            for(int j = 0;j < k; j++)
                rect[x+i][y+j] = val;
        }
};