Algorithm/BOJ

백준 17142 연구소 3

삼쓰 웅쓰 2021. 3. 17. 16:09
728x90

출처: www.acmicpc.net/problem/17142

분류: 완전탐색, BFS, DFS


접근방식

조합과 BFS를 사용해 해결할 수는 문제였습니다.

바이러스가 활성화될 수 있는 지역과 최대 활성화시킬 수 있는 바이러스의 수가 주어졌을 때,
활성화 바이러스의 조합을 뽑아 BFS를 돌려 최단 거리를 계산합니다.

활성화 바이러스의 조합은 순서 상관없이 뽑는 경우의 수이기 때문에 순열이 아닌 조합으로 처리해줘야 합니다!

var selected = [Point]()
func selectVirus(curr: Int) {
    if selected.count == nm[1] {
        let time = infectTime(selected)
        if time != -1 {
            if minimumTime == -1 {
                minimumTime = time
            } else if minimumTime > time {
                minimumTime = time
            }
        }
        return
    }
    
    guard curr < virusArea.count else { return }
    selected.append(virusArea[curr])
    selectVirus(curr: curr+1)
    selected.removeLast()
    selectVirus(curr: curr+1)
}
조합에 대한 자세한 설명이 궁금하시면 여기를 참고해주세요 :)

주의할 점은 활성화되지 않은 바이러스 지역은 시간계산에 포함시키면 안 된다는 것입니다.

2 2
2 2 

와 같이 모두 바이러스 지역일 경우에 하나만 활성화 시켜서

2 *
* *

를 생각해야 할 때 걸리는 시간은 0입니다.

저는 바이러스 지역이어도 똑같이 큐에 담아 BFS 계산을 해주고 마지막에 최대 시간을 계산해줄 때만 바이러스 가능 지역은 포함하지 않는 방식으로 구현해줬습니다.

// map에서 1로 벽일 경우만 무시해주고 나머지는 똑같이 큐에 담으면서 거리를 계산함
for next in nexts(curr) where isInRange(next) && map[next.r][next.c] != 1 {
  guard dist[next.r][next.c] < 0 else { continue }
  queue.append(next)
  dist[next.r][next.c] = dist[curr.r][curr.c] + 1
}

// 거리를 계산할 때는 map이 0인 지역만 가지고 처리
var maxTime = 0
for r in 0..<nm[0] {
    for c in 0..<nm[0] {
        guard map[r][c] == 0 else { continue }
        if dist[r][c] == -1 {
            return -1
        } else if maxTime < dist[r][c] {
            maxTime = dist[r][c]
        }
    }
}

 

 

 

배운점

처음에 생각없이 조합이 아니라 순열을 계산해버려서 어마어마한 시간초과를 겪었다. 

그리고 조합에서도 가드처리를 앞에서부터 막아버려서 마지막 수를 처리해주지 못해 틀렸었다. 주의하자!!

아직도 조합 + bfs, dfs + bfs 등등 bfs를 자연스럽게 섞어서 해결해야 하는 문제들에 덜 익숙한 것 같다.