题意
给出$n\times m$的网格,有空白格子和被占据的格子,要把$1\times 2$的骨牌放进网格的空白格子中,骨牌不能重叠,问是否有放满空白格子的唯一解法,有则给出方案,否则输出"Not unique"。
思路
考虑拓扑排序,一个空白格子相邻四个方向的空白格子个数作为这个格子的度数,度数为1说明它只能往那个方向放骨牌,放完一个骨牌就更新其周边空白格子的度数,把度数为1的格子放进拓扑排序的队列,最终能放满整个网格的方案就是唯一解法。
代码实现
#include <cstdio> #include <cstring> #include <queue> #define FOR(i, n) for (int i = 0; i < n; i++) const int N = 2010; char grid[N][N]; int deg[N][N]; int dir[][2] = {0, 1, 0, -1, 1, 0, -1, 0}; int n, m; bool check(int x, int y) { if (x >= 0 && y >= 0 && x < n && y < m && grid[x][y] == '.') return true; return false; } int main() { while (~scanf("%d %d", &n, &m)) { FOR(i, n) memset(deg[i], 0, sizeof(int) * m); FOR(i, n) scanf("%s", grid[i]); FOR(i, n) FOR(j, m) if (grid[i][j] == '.') FOR(k, 4) if (check(i + dir[k][0], j + dir[k][1])) deg[i][j]++; std::queue<int> qx, qy; FOR(i, n) FOR(j, m) if (deg[i][j] == 1) qx.push(i), qy.push(j); while (!qx.empty()) { int x = qx.front(), y = qy.front(); qx.pop(), qy.pop(); FOR(i, 4) { int nx = x + dir[i][0], ny = y + dir[i][1]; if (check(nx, ny)) { if (i == 0) grid[x][y] = '<', grid[nx][ny] = '>'; if (i == 1) grid[x][y] = '>', grid[nx][ny] = '<'; if (i == 2) grid[x][y] = '^', grid[nx][ny] = 'v'; if (i == 3) grid[x][y] = 'v', grid[nx][ny] = '^'; deg[nx][ny] = 0; FOR(j, 4) { int nnx = nx + dir[j][0], nny = ny + dir[j][1]; if (check(nnx, nny) && --deg[nnx][nny] == 1) qx.push(nnx), qy.push(nny); } } } } bool flag = true; FOR(i, n) { FOR(j, m) if (grid[i][j] == '.') { flag = false; puts("Not unique"); break; } if (!flag) break; } if (flag) FOR(i, n) grid[i][m] = '\0', printf("%s\n", grid[i]); } return 0; }