TIL/알고리즘 공부
백준 10026번 Swift 알고리즘 연습 - 적록색약_BFS
여의도사노비
2023. 2. 22. 12:17
728x90
원래 BFS 문제를 다시 풀때마다 함수를 만들어내는게 꽤나 오래 걸렸는데 이젠 좀 익숙해진거 같다. 다만 은근히 문제들마다 조건이 달라서 까딱 잘못하면 조건을 만족시키기 못하는 경우가 있으니 이를 유의하는게 좋겠다.
이 문제를 풀면서 생각한 논리적 흐름은
- 다른 BFS 문제들과 비슷한 과정을 겪는다.
- 우선 Graph를 그려주고, 움직일 수 있는 방향을 설정해준다.
- 그리고 내가 해당 위치를 방문했는지 안했는지 visited 배열을 이용해 확인해준다.
- 이 문제의 경우 적록색약인 경우 R과 G를 동일하게 판단해야하고
- 적록색약이 아닌 경우 R G B를 각각의 값으로 봐주어야 하기 때문에 bfs 함수에도 이를 반영해야한다.
- 따라서 colorWeak이 true인 경우 RG를 묶어서 한번에 이동하고
- false인 경우는 R G B 라인을 동서남북 이동하면서 visited 표시를 남긴다.
- 이렇게 하면 같은 값을 이루어진 이어진 구역을 찾을 수 있고 bfs 함수가 종료된 후 count + 1 해주면 각 구역의 개수를 구할 수 있다.
* 10026번
import Foundation
let n = Int(readLine()!)!
var graph = [[String]]()
var visited = [[Bool]]()
var count = [0, 0]
let dx = [-1, 1, 0, 0], dy = [0, 0, -1, 1]
for _ in 0..<n {
graph.append(readLine()!.map{ String($0) })
visited.append(Array(repeating: false, count: n))
}
// 적록색약이 아닌 경우
for i in 0..<n {
for j in 0..<n {
if !visited[i][j] {
bfs(i, j, colorWeak: false)
count[0] += 1
}
}
}
// 초기화
visited = Array(repeating: Array(repeating: false, count: n), count: n)
// 적록색약의 경우
for i in 0..<n {
for j in 0..<n {
if !visited[i][j] {
bfs(i, j, colorWeak: true)
count[1] += 1
}
}
}
print("\(count[0]) \(count[1])")
func bfs(_ x: Int, _ y: Int, colorWeak: Bool) {
var queue = [[x, y]]
let color = graph[x][y]
visited[x][y] = true
while !queue.isEmpty {
let current = queue.removeFirst()
for i in 0..<4 {
let nx = current[0] + dx[i]
let ny = current[1] + dy[i]
if 0..<n ~= nx && 0..<n ~= ny && !visited[nx][ny] {
if colorWeak && (color == "R" || color == "G") && (graph[nx][ny] == "R" || graph[nx][ny] == "G") {
queue.append([nx, ny])
visited[nx][ny] = true
}
else if graph[nx][ny] == color {
queue.append([nx, ny])
visited[nx][ny] = true
}
}
}
}
}
정리(Today I Learned)
- 이전 '현수막' 문제를 풀면서 나에게 조금 더 직관적인 코드가 어떤 것인지 고민했는데, 이번 문제에서 확실히 답을 찾은 것 같다. 컴퓨터에겐 아무런 의미가 없을지라도... 코드를 작성하는 내 입장에서 보여지는 것이 상당히 중요하기 때문에 visited 배열 설정이나 dx dy 방향 설정 등이 의미가 있는 것 같다. 앞으로도 비슷한 형태를 유지하여 문제를 풀어봐야겠다.