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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
|
import Foundation
var n = 0
// 2x3 블록을 확인하기 위한 x, y 인덱스 모음
let block2x3 = [[0, 0, 0, 1, 1, 1], [0, 0, 1, 1, 2, 2]]
// 3x2 블록을 확인하기 위한 x, y 인덱스 모음
let block3x2 = [[0, 1, 2, 0, 1, 2], [0, 1, 0, 1, 0, 1]]
// x, y값이 인덱스에서 벗어나는지를 판정
func isXYsafe(_ x: Int, _ y: Int, _ n: Int) -> Bool {
return min(x, y) >= 0 && max(x, y) < n
}
func possible(_ x: Int, _ y: Int, _ k: Int, _ count: [[Int]], _ matrix: [[Int]], _ check: [[Int]], _ n: Int) -> ([[Int]], [[Int]], [[Int]], Bool) {
var col = -1
var cur = 0
var check = check
for i in 0 ..< 6 {
let nx = x + block2x3[k][i]
let ny = y + block3x2[k][i]
// 같은 숫자가 4개 있고 0이 두개인 6개짜리 블록을 찾는다
if isXYsafe(nx, ny, n) {
if matrix[nx][ny] != 0 {
if col == -1 {
col = matrix[nx][ny]
} else {
if col != matrix[nx][ny] {
return (count, matrix, check, false)
}
}
} else {
cur += 1
// 보드에서 0인 곳이 count에서 0이 아니라면 블록 아래쪽이라는 말이므로 연산 종료
if count[nx][ny] != 0 {
return (count, matrix, check, false)
}
}
} else {
return (count, matrix, check, false)
}
}
if cur != 2 {
return (count, matrix, check, false)
}
// 블록을 지울 수 있었던 경우
for i in 0 ..< 6 {
let nx = x + block2x3[k][i]
let ny = y + block3x2[k][i]
check[nx][ny] = 1 // true 대신 1로 함
}
// while 연산을 한번 더 하도록 함
return (count, matrix, check, true)
}
func solution(_ board:[[Int]]) -> Int {
n = board.count
var answer = 0
var possi = Bool()
// 입력받는 행렬, 블록 체크 후 지워지는것도 반영
var board = board
// 검은 블록을 내릴 수 있는지 판정하는 보드
var count = Array(repeating: Array(repeating: 0, count: n), count: n)
// 지워야 할 블록을 알려주는 행렬
var check = Array(repeating: Array(repeating: 0, count: n), count: n)
while true {
// count, check보드 초기확
for i in 0 ..< n {
for j in 0 ..< n {
count[i][j] = 0
check[i][j] = 0
}
}
var flag = false
// board 정보로부터 count 보드를 작성. 블록이 있는지만 우선 판정
for i in 0 ..< n {
for j in 0 ..< n {
if board[i][j] > 0 {
count[i][j] = 1
} else {
count[i][j] = 0
}
}
}
// 블록 값을 밑으로 내리면서 계속 더한다. 그럼 검은 블록은 블록 밑에 올 수 없음
for i in 1 ..< n {
for j in 0 ..< n {
count[i][j] += count[i-1][j]
}
}
for i in 0 ..< n {
for j in 0 ..< n {
for k in 0 ..< 2 {
(count, board, check, possi) = possible(i, j, k, count, board, check, n)
if possi {
// 연산이 끝나지 않았으므로 루프를 다시 실행시킴
flag = true
answer += 1
}
}
}
}
// 지워질 수 있는 행렬을 check보드로 판정 후 board에서 삭제
for i in 0 ..< n {
for j in 0 ..< n {
if check[i][j] == 1 {
board[i][j] = 0
}
}
}
if !flag {
break
}
}
return answer
}
|