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

[Swift Algorithm] 미둜 탐색 BOJ #2178

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

N×M크기의 λ°°μ—΄λ‘œ ν‘œν˜„λ˜λŠ” λ―Έλ‘œκ°€ μžˆλ‹€.

1 0 1 1 1 1
1 0 1 0 1 0
1 0 1 0 1 1
1 1 1 0 1 1

λ―Έλ‘œμ—μ„œ 1은 이동할 수 μžˆλŠ” 칸을 λ‚˜νƒ€λ‚΄κ³ , 0은 이동할 수 μ—†λŠ” 칸을 λ‚˜νƒ€λ‚Έλ‹€. μ΄λŸ¬ν•œ λ―Έλ‘œκ°€ μ£Όμ–΄μ‘Œμ„ λ•Œ, (1, 1)μ—μ„œ μΆœλ°œν•˜μ—¬ (N, M)의 μœ„μΉ˜λ‘œ 이동할 λ•Œ μ§€λ‚˜μ•Ό ν•˜λŠ” μ΅œμ†Œμ˜ μΉΈ 수λ₯Ό κ΅¬ν•˜λŠ” ν”„λ‘œκ·Έλž¨μ„ μž‘μ„±ν•˜μ‹œμ˜€. ν•œ μΉΈμ—μ„œ λ‹€λ₯Έ 칸으둜 이동할 λ•Œ, μ„œλ‘œ μΈμ ‘ν•œ 칸으둜만 이동할 수 μžˆλ‹€.

μœ„μ˜ μ˜ˆμ—μ„œλŠ” 15칸을 μ§€λ‚˜μ•Ό (N, M)의 μœ„μΉ˜λ‘œ 이동할 수 μžˆλ‹€. 칸을 μ…€ λ•Œμ—λŠ” μ‹œμž‘ μœ„μΉ˜μ™€ 도착 μœ„μΉ˜λ„ ν¬ν•¨ν•œλ‹€.

 

μž…λ ₯

첫째 쀄에 두 μ •μˆ˜ N, M(2 ≤ N, M ≤ 100)이 주어진닀. λ‹€μŒ N개의 μ€„μ—λŠ” M개의 μ •μˆ˜λ‘œ λ―Έλ‘œκ°€ 주어진닀. 각각의 μˆ˜λ“€μ€ λΆ™μ–΄μ„œ μž…λ ₯으둜 주어진닀.

 

좜λ ₯

첫째 쀄에 μ§€λ‚˜μ•Ό ν•˜λŠ” μ΅œμ†Œμ˜ μΉΈ 수λ₯Ό 좜λ ₯ν•œλ‹€. 항상 λ„μ°©μœ„μΉ˜λ‘œ 이동할 수 μžˆλŠ” 경우만 μž…λ ₯으둜 주어진닀.

 

μž…μΆœλ ₯ 예제

μž…λ ₯

4 6
101111
101010
101011
111011

좜λ ₯

15

 

λ‚΄ 문제 풀이
import Foundation

let size = readLine()!.split(separator: " ").map({Int(String($0))!})
let n = size[0] // μ„Έλ‘œ 길이
let m = size[1] // κ°€λ‘œ 길이
var maze = [[Int]]() // 미둜
var queue = [(0, 0)] // 경둜의 μ’Œν‘œ 값을 담을 큐
let dx = [-1, 1, 0 , 0], dy = [0, 0, -1, 1] // μƒν•˜μ’Œμš° 검색을 μœ„ν•œ μ’Œν‘œ λ³€ν™”λŸ‰

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

// 큐가 빌 λ•ŒκΉŒμ§€ 반볡
while !queue.isEmpty {
    let (x, y) = queue.removeFirst() // FIFO둜 큐의 첫 번째 pop
    
    // 상, ν•˜, 쒌, 우 검색을 μœ„ν•΄ 0λΆ€ν„° 3κΉŒμ§€ 총 4번 반볡
    for i in 0..<4 {
        // ν˜„μž¬ μœ„μΉ˜μ— x, yμΆ• 각각 dx[i], dy[i] 값을 λ”ν•΄μ„œ 검색할 μ’Œν‘œ ꡬ해주기
        let nx = x + dx[i]
        let ny = y + dy[i]
        
        // nx, nyκ°€ 주어진 미둜의 크기에 λ²—μ–΄λ‚˜κ±°λ‚˜, 검색할 μžλ¦¬κ°€ 0일 경우 continue
        if nx < 0 || ny < 0 || nx >= n || ny >= m || maze[nx][ny] == 0 { continue }
        
        // 검색할 μžλ¦¬κ°€ 1일 경우
        if maze[nx][ny] == 1 {
            maze[nx][ny] = maze[x][y] + 1 // κ²€μƒ‰ν•˜λŠ” μžλ¦¬μ— ν˜„μž¬ μžλ¦¬μ—μ„œ 1 λ”ν•œ κ°’ λˆ„μ 
            queue.append((nx, ny)) // 큐에 nx, ny κ°’ μΆ”κ°€
        }
    }
}

print(maze[n-1][m-1])

πŸ‘‰ 1둜 이어진 λͺ¨λ“  경둜λ₯Ό νƒμƒ‰ν•˜λŠ” 것이 포인트!

이어진 μžλ¦¬λ“€μ„ 체크해주어야 ν•œλ‹€λŠ” μ μ—μ„œ 이전에 ν’€μ—ˆλ˜ #1926_κ·Έλ¦Όλ¬Έμ œμ™€ λΉ„μŠ·ν•˜λ‹€.

  • 1이 μ±„μ›Œμ§„ λͺ¨λ“  경둜둜 ν•œ μΉΈμ”© λ‚˜μ•„κ°€λ©΄μ„œ, λͺ©μ μ§€κΉŒμ§€μ˜ 길이λ₯Ό κ΅¬ν•˜λŠ” λ¬Έμ œμ΄λ‹€.
    λ”°λΌμ„œ μ–΄λ””κΉŒμ§€ 경둜λ₯Ό νƒμƒ‰ν–ˆλŠ”μ§€ μ—…λ°μ΄νŠΈν•΄μ€„ 수 μžˆλŠ” 큐가 ν•„μš”ν•˜λ‹€.
    queueλΌλŠ” μ΄λ¦„μœΌλ‘œ 배열을 μƒμ„±ν•˜κ³ , (0, 0)λΆ€ν„° 탐색할 μ˜ˆμ •μ΄λ―€λ‘œ (0, 0)을 λ¨Όμ € μ €μž₯ν–ˆλ‹€.
    그리고 μƒν•˜μ’Œμš° λͺ¨λ“  경둜λ₯Ό κ³ λ €ν•΄μ€˜μ•Όν•˜λ―€λ‘œ, dx, dy λ°°μ—΄λ‘œ μ’Œν‘œ λ³€ν™”λŸ‰μ„ ν‘œν˜„ν•΄μ£Όμ—ˆλ‹€.
  • while을 μ‚¬μš©ν•΄μ„œ 더이상 탐색할 κ²½λ‘œκ°€ μ—†μ–΄μ§ˆ λ•ŒκΉŒμ§€ λ°˜λ³΅ν–ˆλ‹€.
    μš°μ„  queue에 κ°€μž₯ λ¨Όμ € μ €μž₯됐던 값을 κΊΌλ‚΄μ„œ x, y에 μ €μž₯ν•΄μ£Όμ—ˆλ‹€.
    그리고 μƒν•˜μ’Œμš°λ₯Ό λͺ¨λ‘ κ²€μ‚¬ν•˜κΈ° μœ„ν•΄ for문으둜 λ”± 4번 λ°˜λ³΅ν•˜κ²Œ ν–ˆλ‹€.
    nx, ny μƒμˆ˜λ₯Ό 각각 x, y에 μ•Œλ§žλŠ” μ’Œν‘œκ°’μ„ λ”ν•΄μ„œ μ •μ˜ν–ˆλ‹€.
    이 λ•Œ ν˜Ήμ‹œ nxλ‚˜ nyκ°€ 미둜의 크기λ₯Ό λ²—μ–΄λ‚˜κ±°λ‚˜ 0이 ν• λ‹Ήλœ 자리일 κ²½μš°λŠ” μ˜ˆμ™Έμ²˜λ¦¬ν–ˆλ‹€.
    검색할 μžλ¦¬μ— 1이 ν• λ‹Ήλ˜μ–΄μžˆμ„ 경우, 1을 λˆ„μ ν•΄μ€€λ‹€. ((0, 0)λΆ€ν„° (nx, ny)κΉŒμ§€μ˜ 거리λ₯Ό 의미!)
    그리고 queue에 (nx, ny)λ₯Ό appendν•΄μ€ŒμœΌλ‘œμ¨ λ‹€μŒμ— 검사할 경둜λ₯Ό μΆ”κ°€ν•œλ‹€.

 

πŸ’‘ ν”Όλ“œλ°±
  • μ „ν˜•μ μΈ BFSλ¬Έμ œκ°™μ€λ°, 1둜 μ΄μ–΄μ§€λŠ” λͺ¨λ“  경둜의 길이λ₯Ό κ΅¬ν•΄μ£Όμ–΄μ•Όν–ˆλ‹€.
    'μ΅œμ†Œ'길이λ₯Ό κ΅¬ν•΄μ€˜μ•Όν•œλ‹€λŠ” 말에 μ‚¬λ‘œμž‘ν˜€μ„œ μ²˜μŒμ—” λ³΅μž‘ν•˜κ²Œ 풀이λ₯Ό ν•˜λ €λ‹€ μ‹€νŒ¨ν–ˆλŠ”λ°
    κ·Έλƒ₯ BFSλ‹΅κ²Œ λͺ¨λ“  경둜λ₯Ό νƒμƒ‰ν•˜λ©΄ λ˜λŠ”κ²ƒ,,!
  • 계속 문제λ₯Ό 많이 풀어봐야겠당.

 


 

문제

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

λŒ“κΈ€