λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°
3️⃣ Swift/Problem Solving

[Swift Algorithm] ν† λ§ˆν†  BOJ #7659

by seolhee2750 2021. 10. 8.
문제 μ„€λͺ…

철수의 ν† λ§ˆν†  농μž₯μ—μ„œλŠ” ν† λ§ˆν† λ₯Ό λ³΄κ΄€ν•˜λŠ” 큰 μ°½κ³ λ₯Ό 가지고 μžˆλ‹€. ν† λ§ˆν† λŠ” μ•„λž˜μ˜ κ·Έλ¦Όκ³Ό 같이 격자λͺ¨μ–‘ μƒμžμ˜ 칸에 ν•˜λ‚˜μ”© 넣은 λ‹€μŒ, μƒμžλ“€μ„ 수직으둜 μŒ“μ•„ μ˜¬λ €μ„œ 창고에 λ³΄κ΄€ν•œλ‹€.

창고에 λ³΄κ΄€λ˜λŠ” ν† λ§ˆν† λ“€ μ€‘μ—λŠ” 잘 읡은 것도 μžˆμ§€λ§Œ, 아직 읡지 μ•Šμ€ ν† λ§ˆν† λ“€λ„ μžˆμ„ 수 μžˆλ‹€. 보관 ν›„ ν•˜λ£¨κ°€ μ§€λ‚˜λ©΄, 읡은 ν† λ§ˆν† λ“€μ˜ μΈμ ‘ν•œ 곳에 μžˆλŠ” 읡지 μ•Šμ€ ν† λ§ˆν† λ“€μ€ 읡은 ν† λ§ˆν† μ˜ 영ν–₯을 λ°›μ•„ 읡게 λœλ‹€. ν•˜λ‚˜μ˜ ν† λ§ˆν† μ— μΈμ ‘ν•œ 곳은 μœ„, μ•„λž˜, μ™Όμͺ½, 였λ₯Έμͺ½, μ•ž, λ’€ μ—¬μ„― λ°©ν–₯에 μžˆλŠ” ν† λ§ˆν† λ₯Ό μ˜λ―Έν•œλ‹€. λŒ€κ°μ„  λ°©ν–₯에 μžˆλŠ” ν† λ§ˆν† λ“€μ—κ²ŒλŠ” 영ν–₯을 주지 λͺ»ν•˜λ©°, ν† λ§ˆν† κ°€ 혼자 μ €μ ˆλ‘œ μ΅λŠ” κ²½μš°λŠ” μ—†λ‹€κ³  κ°€μ •ν•œλ‹€. μ² μˆ˜λŠ” 창고에 λ³΄κ΄€λœ ν† λ§ˆν† λ“€μ΄ 며칠이 μ§€λ‚˜λ©΄ λ‹€ 읡게 λ˜λŠ”μ§€ κ·Έ μ΅œμ†Œ 일수λ₯Ό μ•Œκ³  μ‹Άμ–΄ ν•œλ‹€.

ν† λ§ˆν† λ₯Ό 창고에 λ³΄κ΄€ν•˜λŠ” 격자λͺ¨μ–‘μ˜ μƒμžλ“€μ˜ 크기와 읡은 ν† λ§ˆν† λ“€κ³Ό 읡지 μ•Šμ€ ν† λ§ˆν† λ“€μ˜ 정보가 μ£Όμ–΄μ‘Œμ„ λ•Œ, 며칠이 μ§€λ‚˜λ©΄ ν† λ§ˆν† λ“€μ΄ λͺ¨λ‘ μ΅λŠ”μ§€, κ·Έ μ΅œμ†Œ 일수λ₯Ό κ΅¬ν•˜λŠ” ν”„λ‘œκ·Έλž¨μ„ μž‘μ„±ν•˜λΌ. 단, μƒμžμ˜ 일뢀 μΉΈμ—λŠ” ν† λ§ˆν† κ°€ λ“€μ–΄μžˆμ§€ μ•Šμ„ μˆ˜λ„ μžˆλ‹€.

 

μž…λ ₯

첫 μ€„μ—λŠ” μƒμžμ˜ 크기λ₯Ό λ‚˜νƒ€λ‚΄λŠ” 두 μ •μˆ˜ M,Nκ³Ό μŒ“μ•„μ˜¬λ €μ§€λŠ” μƒμžμ˜ 수λ₯Ό λ‚˜νƒ€λ‚΄λŠ” Hκ°€ 주어진닀. M은 μƒμžμ˜ κ°€λ‘œ 칸의 수, N은 μƒμžμ˜ μ„Έλ‘œ 칸의 수λ₯Ό λ‚˜νƒ€λ‚Έλ‹€. 단, 2 ≤ M ≤ 100, 2 ≤ N ≤ 100, 1 ≤ H ≤ 100 이닀. λ‘˜μ§Έ μ€„λΆ€ν„°λŠ” κ°€μž₯ λ°‘μ˜ μƒμžλΆ€ν„° κ°€μž₯ μœ„μ˜ μƒμžκΉŒμ§€μ— μ €μž₯된 ν† λ§ˆν† λ“€μ˜ 정보가 주어진닀. 즉, λ‘˜μ§Έ 쀄뢀터 N개의 μ€„μ—λŠ” ν•˜λ‚˜μ˜ μƒμžμ— λ‹΄κΈ΄ ν† λ§ˆν† μ˜ 정보가 주어진닀. 각 μ€„μ—λŠ” μƒμž κ°€λ‘œμ€„μ— λ“€μ–΄μžˆλŠ” ν† λ§ˆν† λ“€μ˜ μƒνƒœκ°€ M개의 μ •μˆ˜λ‘œ 주어진닀. μ •μˆ˜ 1은 읡은 ν† λ§ˆν† , μ •μˆ˜ 0 은 읡지 μ•Šμ€ ν† λ§ˆν† , μ •μˆ˜ -1은 ν† λ§ˆν† κ°€ λ“€μ–΄μžˆμ§€ μ•Šμ€ 칸을 λ‚˜νƒ€λ‚Έλ‹€. μ΄λŸ¬ν•œ N개의 쀄이 H번 λ°˜λ³΅ν•˜μ—¬ 주어진닀.

ν† λ§ˆν† κ°€ ν•˜λ‚˜ 이상 μžˆλŠ” 경우만 μž…λ ₯으둜 주어진닀.

 

좜λ ₯

μ—¬λŸ¬λΆ„μ€ ν† λ§ˆν† κ°€ λͺ¨λ‘ 읡을 λ•ŒκΉŒμ§€ μ΅œμ†Œ 며칠이 κ±Έλ¦¬λŠ”μ§€λ₯Ό κ³„μ‚°ν•΄μ„œ 좜λ ₯ν•΄μ•Ό ν•œλ‹€. λ§Œμ•½, μ €μž₯될 λ•ŒλΆ€ν„° λͺ¨λ“  ν† λ§ˆν† κ°€ μ΅μ–΄μžˆλŠ” μƒνƒœμ΄λ©΄ 0을 좜λ ₯ν•΄μ•Ό ν•˜κ³ , ν† λ§ˆν† κ°€ λͺ¨λ‘ μ΅μ§€λŠ” λͺ»ν•˜λŠ” 상황이면 -1을 좜λ ₯ν•΄μ•Ό ν•œλ‹€.

 

μž…μΆœλ ₯ 예제

μž…λ ₯

5 3 1
0 -1 0 0 0
-1 -1 0 1 1
0 0 0 1 1

좜λ ₯

-1

 

λ‚΄ 문제 풀이
let info = readLine()!.split(separator: " ").map({Int(String($0))!})
let m = info[0] // μƒμž κ°€λ‘œ 칸의 수
let n = info[1] // μƒμž μ„Έλ‘œ 칸의 수
let h = info[2] // μŒ“μ•„μ˜¬λ¦¬λŠ” μƒμžμ˜ 수
var box = Array(repeating: [[Int]](), count: h)
var queue = [(Int, Int, Int)]()
let dz = [-1, 1, 0, 0, 0, 0], dx = [0, 0, -1, 1, 0 , 0], dy = [0, 0, 0, 0, -1, 1] // μœ„μ•„λž˜, μƒν•˜μ’Œμš° 검색을 μœ„ν•œ μ’Œν‘œ λ³€ν™”λŸ‰
var empty = 0
var count = 0

for i in 0..<h {
    for _ in 0..<n {
        box[i].append(readLine()!.split(separator: " ").map({Int(String($0))!}))
    }
}

func bfs() {
    var index = 0
    
    while index < queue.count {
        let (z, x, y) = queue[index]
        index += 1
        
        for j in 0..<6 {
            let nz = z + dz[j]
            let nx = x + dx[j]
            let ny = y + dy[j]
            
            if nz < 0 || nx < 0 || ny < 0 || nz >= h || nx >= n || ny >= m { continue } // μ˜ˆμ™Έ
            
            // νƒμƒ‰ν•œ μžλ¦¬κ°€ 0일 경우! (이제 μ΅ν˜€μ§ˆ κ²ƒμž„)
            if box[nz][nx][ny] == 0 {
                queue.append((nz, nx, ny)) // 1둜 μ΅ν˜€μ‘ŒμœΌλ―€λ‘œ, μƒˆλ‘œμš΄ 탐색 μ‹œμž‘μ μ΄ μΆ”κ°€λ˜μ–΄μ•Ό 함
                box[nz][nx][ny] = box[z][x][y] + 1 // 이 μžλ¦¬κΉŒμ§€ μ΅ν˜€μ§€λŠ”λ°μ— κ±Έλ¦° μ‹œκ°„μ„ λˆ„μ 
                count += 1 // 읡힌 카운트 λˆ„μ 
            }
        }
    }
}

for z in 0..<h {
    for x in 0..<n {
        for y in 0..<m {
            if box[z][x][y] == 1 { queue.append((z, x, y)) } // 읡은 ν† λ§ˆν†  μœ„μΉ˜λ₯Ό 탐색 μ‹œμž‘μ μœΌλ‘œ μΆ”κ°€
            else if box[z][x][y] == 0 { empty += 1 } // μ•ˆμ΅μ€ ν† λ§ˆν† μ˜ 개수 μ„ΈκΈ°
        }
    }
}

bfs()

empty == 0 ? print(0) : (empty == count ? print(box.flatMap({$0}).flatMap({$0}).max()!-1) : print(-1))

πŸ‘‰ bfs탐색 μ „ 미리 읡은 ν† λ§ˆν† μ˜ μœ„μΉ˜μ™€ μ•ˆμ΅μ€ ν† λ§ˆν† μ˜ 개수λ₯Ό μ„Έκ³  μ‹œμž‘ν•΄μ£ΌλŠ” 것이 포인트!

μ§€λ‚œλ²ˆ ν’€μ΄ν–ˆλ˜ #7576번 λ¬Έμ œμ™€ 거의 λ™μΌν•˜λ―€λ‘œ κ°„λ‹¨νžˆ μ„€λͺ…ν•˜κ² λ‹€.

  • #7576번 λ¬Έμ œλŠ” ν† λ§ˆν†  농μž₯이 2μ°¨μ›μ΄μ—ˆμ§€λ§Œ 이 λ¬Έμ œλŠ” 3μ°¨μ›μ΄λΌλŠ” 점이 λ‹€λ₯΄λ‹€.
    μ΄λŸ¬ν•œ 이유둜 탐색을 ν•  λ•Œ, μƒν•˜μ’Œμš° 4λ°©ν–₯λΏλ§Œμ•„λ‹ˆλΌ μœ„, μ•„λž˜κΉŒμ§€ ν•¨κ»˜ λ΄μ€˜μ•Όν•œλ‹€.
    λ”°λΌμ„œ dz, dx, dy둜 μ’Œν‘œ λ³€ν™”λŸ‰μ„ μ •μ˜ν•˜κ³  bfs ν•¨μˆ˜μ˜ for문을 총 6번 λ°˜λ³΅ν•˜κ²Œ ν–ˆλ‹€.
  • bfs ν•¨μˆ˜ μ‹€ν–‰ μ „μ—λŠ” 3쀑 for문을 μ΄μš©ν•΄ 읡은 ν† λ§ˆν† μ™€ μ•ˆμ΅μ€ ν† λ§ˆν† λ₯Ό μ°Ύμ•„μ€¬λŠ”λ°,
    읡은 ν† λ§ˆν† λŠ” κ·Έ μœ„μΉ˜λ₯Ό 큐에 λ‹΄μ•„μ„œ bfs νƒμƒ‰μ˜ μ‹œμž‘μ μœΌλ‘œ 삼을 수 있게 ν–ˆλ‹€.
    그리고 μ•ˆμ΅μ€ ν† λ§ˆν† λŠ” 개수λ₯Ό μ„Έμ–΄μ„œ, λ§ˆμ§€λ§‰μ— 읡힌 ν† λ§ˆν† μ˜ κ°œμˆ˜μ™€ 비ꡐ할 수 있게 해쀬닀.

(7576번 λ¬Έμ œμ™€ 거의 λ™μΌν•˜λ―€λ‘œ,, μžμ„Έν•œ μ„€λͺ…은 이전 κ²Œμ‹œκΈ€μ„ μ°Έκ³ ν•΄μ£Όμ„Έμš”,,!πŸ’₯)

 

πŸ’‘ ν”Όλ“œλ°±
  • swiftλ₯Ό μ‚¬μš©ν•˜λ©΄μ„œ 3차원 배열을 μ‚¬μš©ν•  일이 거의 μ—†μ—ˆκΈ° λ•Œλ¬Έμ—
    appendν•˜κ±°λ‚˜, flatMap을 μ‚¬μš©ν•˜λŠ” κ³Όμ •μ—μ„œ μ•½κ°„ ν—·κ°ˆλ Έμ§€λ§Œ 금방 ν•΄κ²°ν–ˆλ‹€.
  • 이전에 ν’€μ—ˆλ˜ λ¬Έμ œμ™€ 거의 κ°™μ•„μ„œ 금방 ν’€ 수 μžˆμ—ˆλ‹€.

 


문제

https://www.acmicpc.net/problem/7569

λŒ“κΈ€