cf515d
题意:给出一个矩阵迷宫,要求用1×2的积木填满空白区域,问解法是否唯一,如果无解或者多解均输出“Not unique"。
分析:广搜。看似二分图匹配但实际上不是。
我们认为每个点和上下左右四个点连接(只考虑空白的点)。先把度为1的点全部入队。
每次弹出一个点a,把那个唯一与它链接的点b与a配对。切断b的所有其他边,观察是否有点的度变为1,将这些点入队。
如此循环直到队列为空。如果仍有空白点未覆盖则必然not unique。因为剩下的点的度均大于1(如果有0的那就无解),所以一定有环存在。
环上只要把原来的配对依次串位一格则又是一种方法。
#include <cstdio> #include <cstring> #include <algorithm> #include <queue> using namespace std; #define D(x) const int MAX_N = (int)(2e3) + 10; struct Point { int x, y; Point() {} Point(int x, int y):x(x), y(y) {} Point operator + (const Point &a) { return Point(x + a.x, y + a.y); } }; Point dir[8] = {Point(1, 0), Point(0, 1), Point(-1, 0), Point(0, -1), }; int row_num, col_num; char grid[MAX_N][MAX_N]; bool vis[MAX_N][MAX_N]; Point match[MAX_N][MAX_N]; bool out(Point a) { return a.x < 0 || a.y < 0 || a.x >= row_num || a.y >= col_num; } bool minus_one(Point a) { return a.x == -1 && a.y == -1; } void draw(Point a, char ch) { grid[a.x][a.y] = ch; } void draw(Point a, Point b) { if (a.x > b.x || a.y > b.y) swap(a, b); if (a.x == b.x) { draw(a, '<'); draw(b, '>'); }else { draw(a, '^'); draw(b, 'v'); } } void output() { for (int i = 0; i < row_num; i++) puts(grid[i]); } int get_degree(Point u) { int ret = 0; for (int i = 0; i < 4; i++) { Point v = u + dir[i]; if (out(v) || grid[v.x][v.y] != '.') continue; ret++; } return ret; } bool not_unique() { queue<Point> q; for (int i = 0; i < row_num; i++) { for (int j = 0; j < col_num; j++) { if (get_degree(Point(i, j)) == 1) { q.push(Point(i, j)); } } } while (!q.empty()) { Point u = q.front(); q.pop(); if (grid[u.x][u.y] != '.') continue; D(printf("u %d %d\n", u.x, u.y)); Point v; for (int i = 0; i < 4; i++) { v = u + dir[i]; if (out(v) || grid[v.x][v.y] != '.') continue; draw(u, v); break; } u = v; for (int i = 0; i < 4; i++) { v = u + dir[i]; if (out(v) || grid[v.x][v.y] != '.') continue; if (get_degree(v) == 1) { q.push(v); } } } for (int i = 0; i < row_num; i++) { for (int j = 0; j < col_num; j++) { if (grid[i][j] == '.') { return true; } } } return false; } int main() { scanf("%d%d", &row_num, &col_num); for (int i = 0; i < row_num; i++) { scanf("%s", grid[i]); } if (not_unique()) { puts("Not unique"); return 0; } output(); return 0; }