1 条题解
-
0
自认为代码写的比较优雅。
思路
这道题要求把 个拼图块放入网格中。每个拼图块可以旋转,因此对于每个拼图块,需要枚举它的 种方向。
我们按照从上到下、从左到右的顺序依次填格子。
对于每块拼图,我们检查它与上方和左方已经填好的拼图(或是边缘)是否合法即可。
代码
#include <bits/stdc++.h> using namespace std; const int N=105; struct Node { int id;char e[4]; }p[N],g[15][15]; int R,C,n; bool vis[N]; bool check(int x, int y, char e[4]) { if (x == 1 and e[0] != '0') return false; if (x == R and e[2] != '0') return false; if (y == 1 and e[3] != '0') return false; if (y == C and e[1] != '0') return false; if (x > 1 and g[x - 1][y].e[2] != e[0]) return false; if (y > 1 and g[x][y - 1].e[1] != e[3]) return false; return true; } bool dfs(int x,int y) { if(x>R )return true; int nx=y==C?x+1:x; int ny=y==C?1:y+1; for(int i=1;i<=n;i++) { if(vis[i])continue; vis[i]=true; char cur[4]; for(int k=0;k<4;k++)cur[k]=p[i].e[k]; for(int k=0;k<4;k++) { if(check(x,y,cur)) { g[x][y].id=p[i].id; for(int j=0;j<4;j++)g[x][y].e[j]=cur[j]; if(dfs(nx,ny))return true; } rotate(cur,cur+3,cur+4); }vis[i]=false; }return false; } int main() { cin.tie(0)->sync_with_stdio(0); cin>>R>>C;n=R*C; for(int i=1;i<=n;i++) { cin>>p[i].id; for(int j=0;j<4;j++)cin>>p[i].e[j]; } dfs(1,1); for (int i = 1; i <= R; i++) { for (int j = 1; j <= C; j++) { cout << g[i][j].id << " " << g[i][j].e[0] << " " << g[i][j].e[1] << " " << g[i][j].e[2] << " " << g[i][j].e[3] << "\n"; } } return 0; }std::rotate的作用std::rotate是 C++ STL 中非常强大且优雅的一个算法函数,专门用来处理数组、vector等序列的循环左移操作。它的基本用法和参数含义非常直观。可以把它想象成:把一个序列变成一个环,然后转动一段距离,再重新切开。
函数原型
std::rotate(first, middle, last);它接收三个迭代器或指针作为参数:
first:指向需要旋转的序列开头。middle:指向旋转后新序列第一个元素的位置。last:指向序列的结尾,也就是最后一个元素的下一个位置,符合 STL 左闭右开的原则,即 。
执行逻辑
std::rotate会把 这一段区间的元素整体移动到序列的最前面,把原来的 这一段区间的元素整体移动到序列的末尾。复杂度
最坏情况下会枚举拼图块的排列和旋转,复杂度为 。但本题数据中边缘字母较多,匹配限制很强,搜索可以很快剪枝。
- 1
信息
- ID
- 846
- 时间
- 1000ms
- 内存
- 128MiB
- 难度
- 5
- 标签
- 递交数
- 21
- 已通过
- 13
- 上传者