用最少的正方形平铺矩形(C++)


假设我们有一个大小为 n x m 的矩形。我们需要找到可以平铺该矩形的最小数量的整数边长方形物体。

因此,如果输入像 n = 2 和 m = 3,

则输出将为 3,因为我们需要三个块。

为了解决这个问题,我们将遵循以下步骤:

  • 定义一个映射 m

  • res := inf

  • 定义一个函数 dfs(),它将接收 n、m、数组 h、cnt,

  • 如果 cnt >= res,则:

    • 返回

  • isFull := true

  • pos := -1,minH := inf

  • 初始化 i := 1,当 i <= n 时,更新(i 增加 1),执行:

    • 如果 h[i] < m,则:

      • isFull := false

    • 如果 h[i] < minH,则:

      • minH := h[i]

      • pos := i

  • 如果 isFull 不为零,则:

    • res := res 和 cnt 的最小值

    • 返回

  • key := 0

  • base := m + 1

  • 初始化 i := 1,当 i <= n 时,更新(i 增加 1),执行:

    • key := key + h[i] * base

    • base := base * (m + 1)

  • 如果 key 在 s 中并且 s[key] <= cnt,则:

    • 返回

  • s[key] := cnt

  • end := pos

  • 当 (end + 1 <= n 且 h[end + 1] 等于 h[pos] 且 (end + 1 - pos + 1 + minH)

  • <= m) 时,执行:

    • (end 增加 1)

  • 初始化 j := end,当 j >= pos 时,更新(j 减小 1),执行:

    • curH := j - pos + 1

    • 定义一个大小为 n + 1 的数组 next

    • 初始化 i := 1,当 i <= n 时,更新(i 增加 1),执行:

      • next[i] := h[i]

    • 初始化 k := pos,当 k <= j 时,更新(k 增加 1),执行:

      • next[k] := next[k] + curH

    • dfs(n, m, next, cnt + 1)

  • 从主方法执行以下操作:

  • 如果 n 等于 m,则:

    • 返回 1

  • 如果 n > m,则

    • 交换(n, m)

  • 定义一个大小为 n + 1 的数组 h

  • dfs(n, m, h, 0)

  • 返回 res

让我们看看以下实现,以便更好地理解:

示例

实时演示

#include <bits/stdc++.h>
using namespace std;
class Solution {
   public:
   map<int, int> s;
   int res = INT_MAX;
   void dfs(int n, int m, vector<int> h, int cnt){
      if (cnt >= res)
         return;
      bool isFull = true;
      int pos = -1, minH = INT_MAX;
      for (int i = 1; i <= n; i++) {
         if (h[i] < m)
            isFull = false;
         if (h[i] < minH) {
            minH = h[i];
            pos = i;
         }
      }
      if (isFull) {
         res = min(res, cnt);
         return;
      }
      long key = 0;
      long base = m + 1;
      for (int i = 1; i <= n; i++) {
         key += h[i] * base;
         base *= m + 1;
      }
      if (s.find(key) != s.end() && s[key] <= cnt)
         return;
      s[key] = cnt;
      int end = pos;
      while (end + 1 <= n && h[end + 1] == h[pos] && (end + 1 - pos + 1 + minH) <= m)
      end++;
      for (int j = end; j >= pos; j--) {
         int curH = j - pos + 1;
         vector<int> next(n + 1);
         for (int i = 1; i <= n; i++)
            next[i] = h[i];
         for (int k = pos; k <= j; k++) {
            next[k] += curH;
         }
         dfs(n, m, next, cnt + 1);
      }
   }
   int tilingRectangle(int n, int m){
      if (n == m)
         return 1;
      if (n > m)
         swap(n, m);
      vector<int> h(n + 1);
      dfs(n, m, h, 0);
      return res;
   }
};
main(){
   Solution ob;
   cout << (ob.tilingRectangle(2, 3));
}

输入

2,3

输出

3

更新于:2020年6月4日

219 次浏览

开启你的 职业生涯

通过完成课程获得认证

立即开始
广告

© . All rights reserved.