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

[Swift Algorithm] λ²½ λΆ€μˆ˜κ³  μ΄λ™ν•˜κΈ° BOJ #2206

by seolhee2750 2022. 1. 26.
문제

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

 

2206번: λ²½ λΆ€μˆ˜κ³  μ΄λ™ν•˜κΈ°

N×M의 ν–‰λ ¬λ‘œ ν‘œν˜„λ˜λŠ” 맡이 μžˆλ‹€. λ§΅μ—μ„œ 0은 이동할 수 μžˆλŠ” 곳을 λ‚˜νƒ€λ‚΄κ³ , 1은 이동할 수 μ—†λŠ” 벽이 μžˆλŠ” 곳을 λ‚˜νƒ€λ‚Έλ‹€. 당신은 (1, 1)μ—μ„œ (N, M)의 μœ„μΉ˜κΉŒμ§€ μ΄λ™ν•˜λ € ν•˜λŠ”λ°, μ΄λ•Œ μ΅œλ‹¨ 경둜

www.acmicpc.net

 

λ‚΄ 문제 풀이
let nm = readLine()!.split(separator: " ").map({Int(String($0))!})
let n = nm[0]
let m = nm[1]
var map = [[Int]]()
var result = 0
var queue = [(Int, Int, Int)]()
let dx = [0, 0, -1, 1]
let dy = [-1, 1, 0, 0]
var visited = Array(repeating: Array(repeating: [0, 0], count: m), count: n)

for _ in 0..<n { map.append(Array(readLine()!).map{Int(String($0))!}) }

func bfs() -> Int {
    queue.append((0, 0, 1))
    visited[0][0][1] = 1
    var index = 0
    
    while queue.count > index {
        let (x, y, z) = queue[index]
        index += 1
        
        if (x, y) == (n-1, m-1) { return visited[x][y][z] }
        
        for i in 0..<4 {
            let nx = x + dx[i]
            let ny = y + dy[i]
            
            if nx < 0 || ny < 0 || nx >= n || ny >= m { continue }
            
            if visited[nx][ny][z] == 0 {
                // 벽이고, 벽을 λΆ€μˆ˜μ§€ μ•Šμ•˜λ˜ 경우 => λΆ€μˆ  수 μžˆλŠ” 경우
                if map[nx][ny] == 1 && z == 1 {
                    visited[nx][ny][0] = visited[x][y][1] + 1
                    queue.append((nx, ny, 0))
                }
                // 벽이 아닐 경우
                else if map[nx][ny] == 0 {
                    visited[nx][ny][z] = visited[x][y][z] + 1
                    queue.append((nx, ny, z))
                }
            }
        }
    }
    
    return -1
}

print(bfs())

πŸ‘‰ bfs 문제둜, 3차원 배열을 λ§Œλ“€μ–΄μ„œ μžλ¦¬λ§ˆλ‹€ 벽을 λΆ€μ‰ˆλŠ”μ§€, λΆ€μˆ˜μ§€ μ•Šκ³  μ΄λ™ν–ˆλŠ”μ§€ μ²΄ν¬ν•΄μ£ΌλŠ”κ²Œ 포인트,,!

이 λ¬Έμ œλŠ” 경둜λ₯Ό νƒμƒ‰ν•˜λ©΄μ„œ, 벽을 λΆ€μˆ˜κ³  μ™”λŠ”μ§€ μ•„λ‹ˆλ©΄ λΆ€μˆ˜μ§€ μ•Šκ³  μ™”λŠ”μ§€λ₯Ό ν•¨κ»˜ νŒŒμ•…ν•΄μ£Όμ–΄μ•Ό ν•˜λ―€λ‘œ
2차원 λ°°μ—΄μ—μ„œ 3차원 λ°°μ—΄λ‘œ ν™•μž₯ν•˜μ—¬ (벽을 λΆ€μˆ˜κ³  온 경우) / (λΆ€μˆ˜μ§€ μ•Šκ³  온 경우)둜 λ‚˜λˆ„μ–΄ μ²΄ν¬ν•΄μ•Όν•œλ‹€.

 

[ λ³€μˆ˜ μ„€λͺ… ]

  • queueλŠ” bfs ν•¨μˆ˜μ—μ„œ 탐색할 μžλ¦¬λ“€μ„ λˆ„μ ν•˜λŠ” 배열이닀.
    (xμ’Œν‘œ, yμ’Œν‘œ, λΆ€μˆœ 적 μžˆλŠ”μ§€(0)/λΆ€μˆœ 적 μ—†λŠ”μ§€(1)) ν˜•νƒœλ‘œ μ €μž₯ν•  수 있게 ν–ˆλ‹€.
  • dx, dyλŠ” 탐색할 μ’Œν‘œλ₯Ό λ§Œλ“€κΈ° μœ„ν•œ 배열이닀.
  • visitedλŠ” μžλ¦¬λ§ˆλ‹€ λ°©λ¬Έ μ—¬λΆ€λ₯Ό μ²΄ν¬ν•˜κ³ , ν•΄λ‹Ή μžλ¦¬κΉŒμ§€ κ±Έλ¦° μ‹œκ°„μ„ μ €μž₯ν•˜λŠ” 배열이닀.
    3μ°¨μ›μœΌλ‘œ ν™•μž₯ν•΄μ„œ 'λΆ€μˆœ 이λ ₯이 μžˆλŠ”μ§€ / λΆ€μˆœ 적 μ—†λŠ”μ§€'κΉŒμ§€ 확인할 수 있게 ν–ˆλ‹€.
    [x][y][0]에 0 μ΄μƒμ˜ 값이 μ €μž₯λœλ‹€λ©΄ ν•œ 번 λΆ€μˆœμ  μžˆλŠ” μƒνƒœλ‘œ (x, y)에 λ°©λ¬Έν–ˆλ‹€λŠ” 의미이고,
    [x][y][1]에 0 μ΄μƒμ˜ 값이 μ €μž₯λœλ‹€λ©΄ λΆ€μˆœ 적은 μ—†λŠ” μƒνƒœλ‘œ (x, y)에 λ°©λ¬Έν–ˆλ‹€λŠ” λœ»μ΄λ‹€.

 

[ bfs ν•¨μˆ˜ μ„€λͺ… ]

  • κ°€μž₯ λ¨Όμ € queue에 탐색을 μ‹œμž‘ν•  μžλ¦¬μ— λŒ€ν•œ 정보λ₯Ό μΆ”κ°€ν•΄μ£Όμ—ˆλ‹€.
    μ‹œμž‘μ μ€ 아직 벽을 λΆ€μˆœ 적 μ—†λŠ” 것이 λ‹Ήμ—°ν•˜λ―€λ‘œ (0, 0, 1)을 μΆ”κ°€ν–ˆλ‹€.
  • 그리고 (0, 0) μ’Œν‘œλ₯Ό λ°©λ¬Έν–ˆκ³  벽은 λΆ€μˆ˜μ§€ μ•Šμ•˜μœΌλ―€λ‘œ
    visited[0][0][1]에 1을 μ €μž₯ν•΄μ£Όμ—ˆλ‹€. (1은 μ΄λ™ν•œ μ‹œκ°„μ„ μ˜λ―Έν•˜λŠ”λ°, λ¬Έμ œμ—μ„œ 주어진 쑰건에 μ˜ν•œλ‹€.)
  • index λ³€μˆ˜λ₯Ό μ‚¬μš©ν•˜μ—¬ removeFirstλ₯Ό ν”Όν•΄μ£Όμ–΄ μ‹œκ°„ λ³΅μž‘λ„λ₯Ό μ€„μ˜€λ‹€.
  • for문을 4번 λ°˜λ³΅ν•˜μ—¬ μƒν•˜μ’Œμš°μ— λŒ€ν•œ μ’Œν‘œκ°’μ„ ꡬ해 νƒμƒ‰ν•˜λ„λ‘ ν–ˆκ³ ,
    탐색할 μžλ¦¬κ°€ map의 λ²”μœ„λ₯Ό λ²—μ–΄λ‚˜μ§€ μ•ŠμœΌλ©° λ°©λ¬Έν•œ 적 μ—†λŠ” κ²½μš°μ— λŒ€ν•΄μ„œ 탐색을 μ§„ν–‰ν–ˆλ‹€.
  • 탐색할 μžλ¦¬μ— 벽이 μžˆμ„ 경우, zκ°€ 1μ΄μ–΄μ•Όλ§Œ 벽을 λΆ€μˆ  수 μžˆλ‹€λŠ” 뜻이 λœλ‹€.
    λ”°λΌμ„œ map[nx][ny] == 1 && z == 1 일 경우λ₯Ό 쑰건으둜 λΉΌμ£Όμ—ˆλ‹€.
    이 λ•ŒλŠ” visited 배열에 ν•΄λ‹Ή 자리의 벽을 λΆ€μ‰ˆλ‹€λŠ” 것을 ν‘œμ‹œν•˜κ³ , κ±Έλ¦° μ‹œκ°„μ„ κΈ°λ‘ν–ˆλ‹€.
    그리고 queue에 μƒˆλ‘­κ²Œ 탐색할 μ’Œν‘œμ™€, 벽을 λΆ€μ‰ˆλ‹€λŠ” 정보λ₯Ό ν•¨κ»˜ μΆ”κ°€ν•΄μ£Όμ—ˆλ‹€.
  • 벽이 없을 κ²½μš°μ—λŠ” z 값은 관계가 μ—†μœΌλ―€λ‘œ 생각해쀄 ν•„μš”κ°€ μ—†λ‹€.
    이 λ•ŒλŠ” 벽이 μžˆμ„ 경우의 쑰건과 같이 μ—¬κΈ°κΉŒμ§€ 온 거리λ₯Ό 기둝해주고,
    이전에 벽을 λΆ€μ‰ˆλŠ”μ§€μ— λŒ€ν•œ 이λ ₯은 κ·ΈλŒ€λ‘œ μ „λ‹¬ν•΄μ£Όμ—ˆλ‹€.
    그리고 μƒˆλ‘­κ²Œ 탐색할 μ’Œν‘œμ™€, λ§ˆμ°¬κ°€μ§€λ‘œ 이전에 벽을 λΆ€μ‰ˆλŠ”μ§€μ— λŒ€ν•œ 이λ ₯도 ν•¨κ»˜ μΆ”κ°€ν–ˆλ‹€.
  • κ°€μž₯ λ¨Όμ € (n-1, m-1) μ’Œν‘œμ— λ„λ‹¬ν•œ κ²½μš°κ°€ κ°€μž₯ μ΅œλ‹¨ μ‹œκ°„μ— λ„μ°©ν•œ κ²½μš°κ°€ λ˜λ―€λ‘œ
    κ·Έ λ•ŒλŠ” ν•΄λ‹Ή μžλ¦¬μ— μ €μž₯된 값을 λ¦¬ν„΄ν–ˆλ‹€.
  • while 반볡이 μ§„ν–‰λ˜λŠ” λ™μ•ˆ ν•œ λ²ˆλ„ (n-1, m-1) μ’Œν‘œμ— λ„λ‹¬ν•˜μ§€ λͺ»ν–ˆλ‹€λ©΄
    도달할 수 μ—†μ—ˆλ‹€λŠ” μ˜λ―Έμ΄λ―€λ‘œ κ·Έ λ•ŒλŠ” -1을 λ¦¬ν„΄ν•˜κ²Œ ν–ˆλ‹€.

 

πŸ’‘ ν”Όλ“œλ°±
  • 3차원 배열을 λ§Œλ“€μ–΄μ„œ ( 벽을 λΆ€μˆœ 경우 / λΆ€μˆ˜μ§€ μ•Šμ€ 경우 ) μ΄λ ‡κ²Œ λ‚˜λˆ μ€„ 생각을 ν•  수 μžˆλ‹€λ©΄
    크게 어렡지 μ•Šμ€ λ¬Έμ œμ˜€λ˜ 것 κ°™μ§€λ§Œ, λ‚˜λŠ” κ·Έ 생각을 ν•˜λŠ”λ°μ— κ½€ μ˜€λž˜κ±Έλ Έλ‹€.
  • μ²˜μŒμ—λŠ” queue에 (x, y, λΆ€μˆœμ  μžˆλŠ”μ§€ true or false) μ΄λ ‡κ²Œ 담도둝 ν•˜κ³ ,
    visited 배열은 mapκ³Ό λ™μΌν•˜κ²Œ 2μ°¨μ›μœΌλ‘œ λ§Œλ“€μ–΄μ„œ κ±Έλ¦° μ‹œκ°„λ“€λ§Œ λˆ„μ ν•˜κ²Œ ν–ˆλŠ”λ°,
    κ·Έλ ‡κ²Œ ν•˜λ‹ˆκΉŒ μ˜ˆμ™Έκ°€ 생기더라,,! κ·Έλž˜μ„œ λ‹€μ‹œ ν’€μ—ˆλ‹€.

    => λ°±μ€€ 질문 κ²€μƒ‰μ—μ„œ 찾은 λ°˜λ‘€
    5 8
    01000000
    01010000
    01010000
    01010011
    00010010

λŒ“κΈ€