铺瓷砖

Posted 929code

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了铺瓷砖相关的知识,希望对你有一定的参考价值。

用边长为整数的正方形填充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;
        
;

leetcode 5241. 铺瓷砖

题意:

你是一位施工队的工长,根据设计师的要求准备为一套设计风格独特的房子进行室内装修。

房子的客厅大小为 n x m,为保持极简的风格,需要使用尽可能少的 正方形 瓷砖来铺盖地面。

假设正方形瓷砖的规格不限,边长都是整数。

请你帮设计师计算一下,最少需要用到多少块方形瓷砖?

 

示例一:

输入:n = 2, m = 3
输出:3
解释:3 块地砖就可以铺满卧室。
     21x1 地砖
     12x2 地砖

示例二:

输入:n = 5, m = 8
输出:5

 

示例三:

输入:n = 11, m = 13
输出:6

提示:

  • 1 <= n <= 13
  • 1 <= m <= 13

 

思路:

思路:我们设dp[i][j]:表示组成一个i*j大小的矩形所需要的最小方案数,我们考虑将当前块分三种情况化为更小的块进行求解:

  • 1.竖直切一刀 
  • 2.水平切一刀 
  • 3.不规则切割,将一个矩形分成5块,其中中间那块是1*1的

其中前两种情况非常好理解,第三种是为什么呢? 为什么中间一定是1*1大小的呢?

首先我们知道这道题的n和m很小,只有13这么大,你在草稿纸上画一画就会发现,其实根本不会出现中间出现类似于2*2大小的块使其无法水平或者竖直分割。

 1 class Solution {
 2 public:
 3     int dp[15][15];
 4     int tilingRectangle(int n, int m) {
 5         memset(dp,0x3f,sizeof(dp));
 6         for(int i=0;i<=m;i++)dp[0][i]=0;
 7         for(int i=0;i<=n;i++)dp[i][0]=0;
 8         for(int i=1;i<=n;i++){
 9             for(int j=1;j<=m;j++){
10                 if(i==j)dp[i][j]=min(dp[i][j],1);
11                 for(int k=1;k<j;k++)dp[i][j]=min(dp[i][j],dp[i][k]+dp[i][j-k]);
12                 for(int k=1;k<i;k++)dp[i][j]=min(dp[i][j],dp[k][j]+dp[i-k][j]);
13                 for(int p=1;p<=i;p++){
14                     for(int q=1;q<=j;q++){
15                         dp[i][j]=min(dp[i][j],1+dp[p-1][q]+dp[i-p+1][q-1]+dp[i-p][j-q+1]+dp[p][j-q]);
16                     }
17                 }
18             }
19         }
20         return dp[n][m];
21     }
22 };
View Code

以上是关于铺瓷砖的主要内容,如果未能解决你的问题,请参考以下文章

leetcode 5241. 铺瓷砖

铺瓷砖问题 (状态压缩动态规划)

LeetCode1240铺瓷砖

数据结构与算法之深入解析“铺瓷砖”的求解思路与算法示例

铺地砖

Problem F: 铺地砖