链接
传送门
题意
给出一些拼图碎片,输出拼好后的\(4*4\)的正方形,无解输出“No solution possible”。
思路
预处理出所有拼图可能的位置的二进制码,然后dfs求解。碎片的个数总是16,可以作为剪枝。
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
| #include <cstdio> #include <cstring> #include <algorithm> using namespace std;
const int maxn = 20; const int aim = (1 << 16) - 1; char s[maxn][maxn]; int n, t; int m[maxn][maxn];
bool dfs(int d, int cur) { if (d > n) { return cur == aim; } for (int i = 1; i <= m[d][0]; ++i) { if ((cur & m[d][i]) == 0 && dfs(d + 1, cur | m[d][i])) { for (int j = 0; j < 16; ++j) { if (m[d][i] & (1 << j)) { s[j / 4][j % 4] = '0' + d; } } return true; } } return false; }
int main() { while (~scanf("%d", &n) && n) { if (t++) { puts(""); } int cnt = 0; memset(m, 0, sizeof m); for (int i = 1; i <= n; ++i) { int r, c; scanf("%d%d", &r, &c); int rr = 5 - r, cc = 5 - c; m[i][0] = rr * cc; for (int j = 0; j < r; ++j) { char s[10]; scanf("%s", s); for (int k = 0; k < c; ++k) { if (s[k] == '1') { ++cnt; for (int x = 0; x < rr; ++x) { for (int y = 0; y < cc; ++y) { m[i][x * cc + y + 1] |= 1 << ((j + x) * 4 + k + y); } } } } } } if (cnt == 16 && dfs(1, 0)) { for (int i = 0; i < 4; ++i) { puts(s[i]); } } else { puts("No solution possible"); } } return 0; }
|