# 문제 설명
- 6방향으로 인접한 건물 각 그룹의 외벽 총 길이를 합산해야 한다.
- 내벽은 계산하지 않고 인접한 건물 한 그룹 내에 비어있는 건물 위치에서도 크기에 상관 없이 벽 갯수로 계산하지 않아야 한다.
# 잘못된 초기 접근 방식
- 건물 입력 과정에서 건물들에 둘러쌓인 내벽을 1로 초기화해주어 아예 하나의 건물 단지로 만드는 로직을 생각했음
- 둘러쌓인 내벽이란, 입력값이 0이면서 6방향 순회 시 전체 입력이 1인 경우를 말한다.
- 반례의 경우, 입력값이 0으로 연속하여 두 위치에 입력되는 경우 6방향 순회가 1이 되지 않는다. 한 곳은 뚫려있지만 여전히 내벽으로 간주해야 한다.
# 올바른 접근 방식
- 건물 입력에 외부 테두리를 추가한다.
- 테두리 아무 위치에서부터 DFS를 시작하여 입력값이 1로 접근이 이루어질 때 리턴값을 1 더해준다. (edge 갯수 하나 증가)
- for문으로 순회 시 문제 조건에 맞추어 (x, y+1) 좌표 변화량을 홀수 짝수에 맞춰 제대로 반영해야 한다.
# 풀이
import Foundation
struct Queue<T> {
var array: [T?] = []
var head = 0
var isEmpty: Bool {
return count == 0
}
var count: Int {
return array.count - head
}
mutating func enqueue(_ element: T) {
array.append(element)
}
mutating func dequeue() -> T? {
guard head < array.count,
let element = array[head] else { return nil }
array[head] = nil
head += 1
let percentage = Double(head) / Double(array.count)
if percentage > 0.25 && array.count > 50 {
array.removeFirst(head)
head = 0
}
return element
}
var front: T? {
if isEmpty {
return nil
} else {
return array[head]
}
}
}
let WH = readLine()!.split(separator: " ").map { Int($0)! }; let W = WH[0]; let H = WH[1]
let dy = [-1, -1, 0, 1, 1, 0]; let dxOdd = [0, 1, 1, 1, 0, -1]; let dxEven = [-1, 0, 1, 0, -1, -1]
var adj: [[Int]] = .init(repeating: .init(repeating: 0, count: W+2), count: H+2)
var visited: [[Bool]] = .init(repeating: .init(repeating: false, count: W+2), count: H+2)
var ret = 0
for i in 1...H {
var row: [Int] = [0]
let input = readLine()!.split(separator: " ").map { Int($0)! }
row += input + [0]
adj[i] = row
}
// 밖에서 DFS 순회 - 외벽 좌표 추가
func dfs(_ y: Int, _ x: Int) {
visited[y][x] = true
for i in 0..<6 {
let ny = dy[i] + y
var nx = 0
if y % 2 == 1 {
nx = dxOdd[i] + x
} else {
nx = dxEven[i] + x
}
if ny < 0 || nx < 0 || ny > H+1 || nx > W+1 || visited[ny][nx] {
continue
}
if adj[ny][nx] == 1 {
ret += 1
continue
}
dfs(ny, nx)
}
}
dfs(0, 0)
print(ret)