백준 9328번 열쇠 (swift) [G1]
BFS
- 시작점 큐에 넣기
- 반복
- 큐에서 꺼내기
- 방문 체크하기
- 갈 수 있는 곳이자 안 간 곳 큐에 넣기
생각회로
- 테두리 BFS 반복 -> 시간초과 ( 100개의 테케를 얕봤다. )
- 열쇠 찾을 때만 다음 BFS 진행 -> 시간초과
- 배열로 큐 대신 큐 구현( 스택 두개로 ) -> 시간초과
- 열쇠 찾으면 모든 문 열기 -> 시간초과
- 열쇠 찾으면 해당 열쇠 모두 제거 -> 시간초과
- 초기 열쇠 중복 제거 -> 시간초과
- 테두리 매 번 찾는 대신, startingPoints 한 번만 구해두기 -> 시간초과
- 알파벳 배열에 미리저장 대신, Swift 5 부터 추가된
Character.isUppercase
사용 -> 시간초과
- 문이지만 갈 곳 추가하기 대신, 문이면 안 가기 ( 열쇠 발견시 초기화때문 ) -> 시간초과
- 시작점이 간 곳이여도 탐색하는 오류 제거 -> 통과

주의사항
- BFS를 얕보지 말자
100(테케)*100(가로)*100(세로)*26(알파벳)*BFS횟수
== 2600만 * BFS횟수
소스코드
import Foundation
class Queue {
var enqueue = [(Int,Int)]()
var dequeue = [(Int,Int)]()
func pop() -> (Int, Int)? {
if dequeue.isEmpty{
if enqueue.isEmpty{
return nil
}else{
dequeue = enqueue.reversed()
enqueue.removeAll()
}
}
return dequeue.popLast()!
}
func append(_ element: (Int,Int) ) {
enqueue.append(element)
}
var isEmpty: Bool {
enqueue.isEmpty && dequeue.isEmpty
}
}
class Solution {
var li: [[String]]
var keys: [String]
let ix = [0,0,1,-1]
let iy = [1,-1,0,0]
var answer: Int = 0
var startPoints = [(Int,Int)]()
init(li: [[String]], keys: [String]) {
self.li = li
self.keys = keys
}
func findOutLine() {
for i in 0..<li.count{
if li[i][0] != "*"{
startPoints.append((i,0))
}
if li[i][li[0].count - 1] != "*" {
startPoints.append((i, li[0].count - 1))
}
}
for i in 0..<li[0].count{
if li[0][i] != "*"{
startPoints.append((0, i))
}
if li[li.count - 1][i] != "*" {
startPoints.append((li.count - 1, i))
}
}
}
func solve() {
findOutLine()
keys.forEach{ foundKeySoClearAllOfDoors($0) }
while searchFromOutline() {
}
print(answer)
}
func foundKeySoClearAllOfDoors(_ key: String) {
for i in 0..<li.count{
for j in 0..<li[0].count{
if keys.contains(li[i][j].lowercased()){
li[i][j] = "."
}
}
}
keys.removeAll()
}
func searchFromOutline() -> Bool {
let q = Queue()
q.dequeue = startPoints
return search(q, li)
}
func search(_ q: Queue,_ _thisLi:[[String]]) -> Bool {
var thisLi = _thisLi
var ret = false
while !q.isEmpty {
let (X, Y) = q.pop()!
if thisLi[X][Y] == "@"{
continue
}
if li[X][Y] == "$" {
answer += 1
li[X][Y] = "."
}
if (li[X][Y].first!).isLowercase {
keys.append(li[X][Y])
li[X][Y] = "."
return true
}
if (li[X][Y].first!).isUppercase {
if keys.contains(li[X][Y].lowercased()) {
li[X][Y] = "."
}else{
continue
}
}
thisLi[X][Y] = "@"
for i in 0..<ix.count {
let (nextX, nextY) = (X+ix[i], Y+iy[i])
if nextX < 0 || nextY < 0 || nextX >= li.count || nextY >= li[0].count{
continue
}
if ["*","@"].contains(thisLi[nextX][nextY]) {
continue
}
q.append((nextX, nextY))
}
}
return ret
}
}
func main() {
let T = Int(readLine()!)!
(0..<T).forEach{ _ in
let hw = readLine()!.split(separator: " ").map{Int($0)!}
var li = Array(repeating: Array(repeating: "", count: hw[1]), count: hw[0])
(0..<hw[0]).forEach{ i in li[i] = readLine()!.map{ String($0)} }
let keys = Set(readLine()!.map{String($0)})
let solution = Solution(li: li, keys: keys.contains("0") ? [] : Array(keys))
solution.solve()
}
}
main()