題目給出一個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;
}