https://www.acmicpc.net/problem/4574
목적
스도미노쿠의 9x9 그리드에 스도쿠 규칙에 따라, (1+2, 1+3, 1+4, 1+5, 1+6, 1+7, 1+8, 1+9, 2+3, 2+4, 2+5, ...)와 같은 도미노 타일 36개를 채워야한다.
접근법
1. 0,0~8,8까지의 범위에서, i, j에 해당하는 좌표를 순서대로 방문
2. 해당 좌표에 놓을 수 있는 타일을 상하좌우 네 방향으로 인접한 좌표까지 고려하여 추려낸다.
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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
|
#include<iostream>
#include<cstring>
#define init(dst) memset(dst,0,sizeof(dst))
#define useNum(i,j,k) usedNum[0][i][k] = usedNum[1][j][k] = usedNum[2][(i / 3) * 3 + j / 3][k]
using namespace std;
int b[9][9], di[] = { 1,-1,0,0 }, dj[] = { 0,0,1,-1 };
bool usedTile[10][10], usedNum[3][10][10];
bool canUseNum(int i,int j,int k) {
return !usedNum[0][i][k] && !usedNum[1][j][k] && !usedNum[2][(i / 3) * 3 + j / 3][k];
}
bool fill(int i,int j) {
if (i == 9) return true;
if (j == 9) return fill(i + 1, 0);
if (b[i][j] != 0) return fill(i, j + 1);
for (int k = 1; k < 10; ++k) {
if (!canUseNum(i,j,k))continue;
useNum(i, j, k) = true;
b[i][j] = k;
for (int d = 0; d < 4; ++d) {
int ni = i + di[d], nj = j + dj[d];
if (ni == -1 || ni == 9 || nj == -1 || nj == 9||b[ni][nj]!=0)continue;
for (int t = 1; t < 10; ++t)if (!usedTile[k][t] && canUseNum(ni, nj, t)) {
usedTile[k][t] = usedTile[t][k] = true;
useNum(ni, nj, t) = true;
b[ni][nj] = t;
if (fill(i, j + 1))return true;
usedTile[k][t] = usedTile[t][k] = false;
useNum(ni, nj, t) = false;
b[ni][nj] = 0;
}
}
useNum(i, j, k) = false;
}
b[i][j] = 0;
return false;
}
void set(string& s,int val) {
int y = s[0] - 'A', x = s[1] - '1';
b[y][x] = val;
useNum(y, x, val) = true;
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
int testCase = 1;
while (true) {
int n; cin >> n;
if (n == 0)break;
init(b);init(usedTile);init(usedNum);
for (int i = 1; i < 10; ++i)usedTile[i][i] = true;
string lu, lv, tmp;int y, x, u, v;
for (int i = 0; i < n; ++i) {
cin >> u >> lu >> v >> lv;
usedTile[u][v] = usedTile[v][u] = true;
set(lu, u);
set(lv, v);
}
for (int i = 1; i < 10; ++i) {
cin >> lu;
set(lu, i);
}
fill(0,0);
cout << "Puzzle " << testCase++ << endl;
for (int i = 0; i < 9; ++i) {
for (int j = 0; j < 9; ++j)cout << b[i][j];
cout << endl;
}
}
}
|
'Problem Solving > BOJ 백준' 카테고리의 다른 글
[ BOJ 백준 1405번 - 미친 로봇 ] 해설 및 코드 (0) | 2019.12.08 |
---|---|
[ BOJ 백준 17136번 - 색종이 붙이기 ] 해설 및 코드 (0) | 2019.12.08 |
[ BOJ 백준 1035번 - 조각 움직이기 ] 해설 및 코드 (0) | 2019.12.08 |
[ BOJ 백준 1339번 - 단어 수학 ] 해설 및 코드 (0) | 2019.12.08 |
[ BOJ 백준 1344번 - 축구 ] 해설 및 코드 (0) | 2019.12.07 |