1 条题解
-
0
题解:拼图组合成正方形问题
问题描述
给定 到 个拼图块,每个拼图块由 和 组成的矩阵表示( 表示实体部分, 表示空白)。要求在不旋转和翻转的情况下,将这些拼图块组合成一个 的正方形。若能成功组合,输出具体排列方式;否则输出 。
算法思路
采用**深度优先搜索(DFS)**算法:
- 输入处理:读取每个拼图块的尺寸 和形状矩阵 。
- DFS 搜索:
- 对于每个拼图块,尝试所有可能的放置位置
- 检查该位置是否能放置(不重叠且不越界)
- 若能放置,则递归处理下一个拼图块
- 若所有拼图块放置完毕且填满 网格,则记录解
- 回溯机制:当某条路径无法找到解时,撤销当前拼图块的放置,尝试其他位置。
复杂度分析
- 时间复杂度:(最坏情况需遍历所有可能组合)
- 空间复杂度:(存储拼图形状和当前布局)
代码实现
#include <iostream> #include <cstdio> #include <cstring> using namespace std; int T; // 拼图块数量 int n[30], m[30]; // 各拼图块尺寸 int a[30][10][10]; // 拼图形状存储 int b[10][10]; // 当前布局 int jg; // 解决方案标记 void dfs(int x) { if (jg) return; // 已找到解则终止 if (x == T) { // 所有拼图块已放置 for (int i = 0; i < 4; i++) for (int j = 0; j < 4; j++) if (!b[i][j]) return; // 未填满则返回 jg = 1; for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) printf("%d", b[i][j]); printf("\n"); } printf("\n"); return; } // 尝试所有可能放置位置 for (int i = 0; i <= 4 - n[x]; i++) { for (int j = 0; j <= 4 - m[x]; j++) { int can_place = 1; // 检查是否可以放置 for (int l = 0; l < n[x] && can_place; l++) for (int h = 0; h < m[x]; h++) if (a[x][l][h] && b[i+l][j+h]) { can_place = 0; break; } if (can_place) { // 放置拼图块 for (int l = 0; l < n[x]; l++) for (int h = 0; h < m[x]; h++) if (a[x][l][h]) b[i+l][j+h] = x + 1; dfs(x + 1); // 处理下一个拼图块 // 回溯 for (int l = 0; l < n[x]; l++) for (int h = 0; h < m[x]; h++) if (a[x][l][h]) b[i+l][j+h] = 0; } } } } int main() { while (1) { scanf("%d", &T); if (!T) break; memset(a, 0, sizeof(a)); memset(b, 0, sizeof(b)); for (int i = 0; i < T; i++) { scanf("%d%d", &n[i], &m[i]); for (int j = 0; j < n[i]; j++) for (int k = 0; k < m[i]; k++) scanf("%1d", &a[i][j][k]); } jg = 0; dfs(0); if (!jg) printf("No solution possible\n\n"); } return 0; }
关键点说明
- DFS 参数: 表示当前正在处理的第 个拼图块(从 开始计数)
- 放置检查:通过双重循环检查目标区域是否全为
- 回溯操作:在递归返回时需要将当前拼图块的影响清除
- 终止条件:当 数组中所有 位置均不为 时找到有效解
示例分析
对于输入:
2 2 2 11 11 2 2 11 11
程序将输出:
1111 1111 0000 0000 No solution possible
说明第一个解不满足全填充条件,最终无解。
- 1
信息
- ID
- 545
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 7
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者