2 条题解

  • 0
    @ 2025-10-24 15:25:41
    • 带注释,更好理解的版本
    • 1、先找到最靠上,最靠左没有铺砖的点
    • 2、然后枚举一块砖铺在这里,砖有横着放和竖着放两种方法
    • 3、递归下去即可!!
    #include <bits/stdc++.h>
    using namespace std;
    
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(0); cout.tie(0);
        
        int n, h, w;
        cin >> n >> h >> w;
        vector<int> a(n), b(n);
        for (int i = 0; i < n; i++) cin >> a[i] >> b[i];
        
        // g[i][j]: 表示 (i, j) 还没有铺砖
        vector<vector<bool>> g(h, vector<bool>(w, false));
        
        // 砖块 i 是否已经用过
        vector<bool> used(n, false);
        
        // 求 (x, y, ux, uy) 内已经铺砖的点数
        auto sum = [&](int x, int y, int ux, int uy) -> int {
            int ans = 0;
            for (int i = x; i <= ux; i++) for (int j = y; j <= uy; j++) {
                ans += g[i][j];
            }
            return ans;
        };
        
        // 将 (x, y, ux, uy) 覆盖为 v
        auto fill = [&](int x, int y, int ux, int uy, bool v) {
            for (int i = x; i <= ux; i++) for (int j = y; j <= uy; j++) {
                g[i][j] = v;
            }
        };
        
        function<bool()> dfs = [&]() -> bool {
            // 第一步: 终止条件  
            if (sum(0, 0, h - 1, w - 1) == h * w) return true;
            
            // 找到最靠上, 然后最靠左没有铺砖的点
            int x = -1, y = -1;
            for (int i = 0; i < h; i++) {
                for (int j = 0; j < w; j++) if (!g[i][j]) {
                    x = i, y = j;
                    break;
                }
                if (x != -1) break;
            }
            
            // 现在我们要找一块砖铺上 (x, y)
            for (int i = 0; i < n; i++) if (!used[i]) {
                
                // i 这块砖可能横着放, 也可能竖着放
                int hi = a[i], wi = b[i];
                for (int j = 0; j < 2; j++) {
                    if (j) swap(hi, wi);
                    
                    // 现在要判断 (x, y) 到 (x + hi - 1, y + wi - 1) 是不是都没铺砖
                    int ux = x + hi - 1, uy = y + wi - 1;
                    if (ux < h && uy < w && sum(x, y, ux, uy) == 0) {
                        // 可以在 (x, y) 到 (x + hi - 1, y + wi - 1) 放砖块 i
                        used[i] = true;
                        fill(x, y, ux, uy, true);
                        if (dfs()) return true;
                        
                        // 铺砖不成功, 记得还原
                        used[i] = false;
                        fill(x, y, ux, uy, false);
                    }
                }
            }
            return false;
        };
        
        // 现在我们开始铺砖
        cout << (dfs() ? "Yes" : "No") << '\n';
        
        return 0;
    }
    
    • 0
      @ 2025-10-22 19:19:33
      • 先找位置
        • 从上到下,从左到右,找到第一个没有被覆盖的位置
        • 再枚举一块能够放在此处的地砖
        • 放置地砖时,还要枚举是横着放,还是竖着放
      // 先找位置,再枚举砖块
      #include <bits/stdc++.h>
      
      using i64 = long long;
      
      int main() {
          std::ios::sync_with_stdio(false);
          std::cin.tie(nullptr);
          
          int N, H, W;
          std::cin >> N >> H >> W;
          
          std::vector<int> A(N), B(N);
          for (int i = 0; i < N; i++) {
              std::cin >> A[i] >> B[i];
          }
          
          std::vector f(H, std::vector<int>(W));
          
          std::vector<int> vis(N);
          auto dfs = [&](auto self, int x, int y) -> void {
              if (x == H) {
                  std::cout << "Yes\n";
                  std::exit(0);
              }
              if (y == W) {
                  return self(self, x + 1, 0);
              }
              if (f[x][y]) {
                  return self(self, x, y + 1);
              }
              for (int i = 0; i < N; i++) {
                  if (!vis[i]) {
                      vis[i] = 1;
                      for (int t = 0; t < 2; t++) {
                          if (x + A[i] <= H && y + B[i] <= W) {
                              int ok = 1;
                              for (int u = 0; u < A[i]; u++) {
                                  for (int v = 0; v < B[i]; v++) {
                                      if (f[x + u][y + v]) {
                                          ok = 0;
                                      }
                                  }
                              }
                              if (ok) {
                                  for (int u = 0; u < A[i]; u++) {
                                      for (int v = 0; v < B[i]; v++) {
                                          f[x + u][y + v] = 1;
                                      }
                                  }
                                  self(self, x, y + 1);
                                  for (int u = 0; u < A[i]; u++) {
                                      for (int v = 0; v < B[i]; v++) {
                                          f[x + u][y + v] = 0;
                                      }
                                  }
                              }
                          }
                          std::swap(A[i], B[i]);
                      }
                      vis[i] = 0;
                  }
              }
          };
          dfs(dfs, 0, 0);
          
          std::cout << "No\n";
          
          return 0;
      }
      
      • 1

      信息

      ID
      144
      时间
      100ms
      内存
      32MiB
      难度
      5
      标签
      递交数
      23
      已通过
      12
      上传者