2 条题解
-
0
- 带注释,更好理解的版本
- 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
- 先找位置
- 从上到下,从左到右,找到第一个没有被覆盖的位置
- 再枚举一块能够放在此处的地砖
- 放置地砖时,还要枚举是横着放,还是竖着放
// 先找位置,再枚举砖块 #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
- 上传者