1 条题解
-
0
题意
这是一个十二面体拼图问题: 十二面体有个五边形面,每个面需要放一块拼图片。 拼图片也是五边形,每条边标有数字、或。
规则: 相邻的两个面(共享一条边)必须满足:它们的公共边数字相同。 拼图片可以旋转(但不能翻转),有种可能的摆放角度。
输入:块拼图片的边标记(每块个数字)。
输出:给出每块拼图片应该放在哪个面,以及如何旋转(用相邻面编号表示旋转角度)。如果无解,输出
解题思路
这道题目要求我们解决一个十二面体拼图问题,需要将块五边形拼图片正确放置在十二面体的个面上,使得相邻拼图片的公共边数字完全相同。
1. 问题建模
十二面体结构:十二面体有个五边形面,每个面与其他个面相邻。题目给出了每个面的相邻关系(数组)。 拼图片:每块拼图片有条边,每条边标记为、或。拼图片可以旋转个不同角度(、、、、)放置。
2. 核心算法:回溯法()
状态表示: :标记拼图片是否已被使用。 :记录十二面体面和面之间共享边的数字(初始为)。 和:记录面上放置的拼图片编号和参考边指向的相邻面。 递归过程:
- 选择拼图片:对于当前面,遍历所有未使用的拼图片。
- 尝试旋转角度:对于拼图片,尝试种旋转角度(对应)。
- 检查合法性:检查拼图片在当前旋转角度下,其边标记是否与相邻面的已有标记匹配。
- 递归下一层:如果合法,标记拼图片为已使用,更新和,递归处理下一个面。
- 回溯:如果递归失败,恢复、和的状态,尝试其他拼图片或旋转角度。
3. 关键优化
剪枝:在递归过程中,如果发现当前拼图片的边标记与相邻面的已有标记冲突,立即终止当前分支的搜索。 状态复制:每次递归调用时,复制当前的状态(),避免直接修改全局状态,简化回溯过程。
4. 输出结果
如果找到解,输出每个面放置的拼图片编号和参考边指向的相邻面。 如果无解,输出。
标程
#include <iostream> #include <cstring> #include <cstdio> using namespace std; bool vis[13]; int tile[13][6], ans[13][2]; int Adjacent[15][6] = { {0, 0, 0, 0, 0, 0}, {0, 2, 3, 4, 5, 6}, {0, 1, 6, 7, 11, 3}, {0, 1, 2, 11, 10, 4}, {0, 1, 3, 10, 9, 5}, {0, 1, 4, 9, 8, 6}, {0, 1, 5, 8, 7, 2}, {0, 8, 12, 11, 2, 6}, {0, 9, 12, 7, 6, 5}, {0, 10, 12, 8, 5, 4}, {0, 11, 12, 9, 4, 3}, {0, 7, 12, 10, 3, 2}, {0, 7, 8, 9, 10, 11} }; int mod(int v) { return (v + 5) % 5; } bool dfs(int cur, int mp[][13]) { if(cur > 12) return true; int mp1[13][13]; for(int i = 1; i <= 12; i++){ if(!vis[i]){ for(int j = 0, k; j < 5; j++){ // 枚举面=tile的5个位置 memcpy(mp1, mp, sizeof(mp1)); for(k = 0; k < 5; k++){ if(mp1[cur][Adjacent[cur][k + 1]] == -1){ // 判断是否合法 mp1[cur][Adjacent[cur][k + 1]] = mp1[Adjacent[cur][k + 1]][cur] = tile[i][mod(j + k)]; }else if(mp1[cur][Adjacent[cur][k + 1]] != tile[i][mod(j + k)]) break; } if(k >= 5){ vis[i] = true; ans[cur][0] = i; ans[cur][1] = Adjacent[cur][mod(5 - j) + 1]; // 记录当前放的tile和参考边所对应的面 if(dfs(cur + 1, mp1)) return true; vis[i] = false; } } } } return false; } int main() { int mp[13][13]; for(int i = 1; i <= 12; i++) for(int j = 0; j < 5; j++) scanf("%d", &tile[i][j]); memset(mp, -1, sizeof(mp)); memset(vis, 0, sizeof(vis)); if(dfs(1, mp)){ for(int i = 1; i <= 12; i++){ printf("%d %d\n", ans[i][0], ans[i][1]); } }else printf("-1\n"); return 0; }
- 1
信息
- ID
- 726
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 20
- 已通过
- 1
- 上传者