题目给出一个n*m的网格,用1*2的砖块将上面的空地都铺满,输出方案是否唯一,若唯一输出解决方案。
把所有的格子当成点,相邻格子间连接一条边,并统计每个格子的度数。将所有度数为1的点放入队列中,度数为1的一定只有一种铺法。铺完更新周围的点的度数,将度数为1的入队,循环直到队列为空。如果此时还没铺满,则方案不唯一。
如果铺完度数为1的,那么剩下的点都是度数>=2,所有的边构成了一个二分图,并且一定存在一个环其中相邻的边可以染成不同颜色。所以如果有解则一定有>=2个解
#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
using namespace std;
#define maxn 2005
int n,m;
char g[maxn][maxn];
int d[maxn][maxn];
int dir[4][2] = {{-1,0},{1,0},{0,1},{0,-1}};
int main()
{
while(scanf("%d%d", &n, &m)!=EOF){
for(int i = 1; i <= n; i++)
scanf("%s", g[i]+1);
memset(d, 0, sizeof(d));
int tot = 0;
queue<int> q;
for(int i = 1; i<= n;i++)
for(int j =1; j<= m; j++){
int nx,ny;
if(g[i][j] != '.') continue;
tot++;
for(int k = 0; k < 4; k++){
nx = i+dir[k][0], ny = j+dir[k][1];
if(g[nx][ny] == '.')
d[i][j]++;
}
if(d[i][j] == 1)
q.push(i*(m+1)+j);
}
int cnt = 0;
while(!q.empty()){
int x = q.front()/(m+1), y = q.front()%(m+1);
q.pop();
for(int i = 0; i < 4; i++){
int nx = dir[i][0]+x, ny = dir[i][1]+y;
if(g[nx][ny] != '.') continue;
if(i == 0){
g[nx][ny] = '^';
g[x][y] = 'v';
}
else if(i == 1){
g[nx][ny] = 'v';
g[x][y] = '^';
}
else if(i == 2){
g[nx][ny] = '>';
g[x][y] = '<';
}
else{
g[nx][ny] = '<';
g[x][y] = '>';
}
cnt+=2;
for(int k = 0; k < 4; k++){
int nnx = nx+dir[k][0], nny = ny+dir[k][1];
if(g[nnx][nny]!='.') continue;
d[nnx][nny]--;
if(d[nnx][nny] == 1)
q.push(nnx*(m+1)+nny);
}
}
}
if(cnt!=tot)
printf("Not unique\n");
else{
for(int i = 1; i <= n; i++){
for(int j = 1; j <= m; j++)
printf("%c", g[i][j]);
printf("\n");
}
}
}
return 0;
}