3️⃣ Swift/Problem Solving

[Swift Algorithm] λ‚˜μ΄νŠΈμ˜ 이동 BOJ #7562

seolhee2750 2021. 10. 11. 22:25
문제 μ„€λͺ…

체슀판 μœ„μ— ν•œ λ‚˜μ΄νŠΈκ°€ 놓여져 μžˆλ‹€. λ‚˜μ΄νŠΈκ°€ ν•œ λ²ˆμ— 이동할 수 μžˆλŠ” 칸은 μ•„λž˜ 그림에 λ‚˜μ™€μžˆλ‹€. λ‚˜μ΄νŠΈκ°€ μ΄λ™ν•˜λ €κ³  ν•˜λŠ” 칸이 μ£Όμ–΄μ§„λ‹€. λ‚˜μ΄νŠΈλŠ” λͺ‡ 번 움직이면 이 칸으둜 이동할 수 μžˆμ„κΉŒ?

 

μž…λ ₯

μž…λ ₯의 첫째 μ€„μ—λŠ” ν…ŒμŠ€νŠΈ μΌ€μ΄μŠ€μ˜ κ°œμˆ˜κ°€ μ£Όμ–΄μ§„λ‹€.

각 ν…ŒμŠ€νŠΈ μΌ€μ΄μŠ€λŠ” μ„Έ μ€„λ‘œ 이루어져 μžˆλ‹€. 첫째 μ€„μ—λŠ” 체슀판의 ν•œ λ³€μ˜ 길이 l(4 ≤ l ≤ 300)이 μ£Όμ–΄μ§„λ‹€. 체슀판의 ν¬κΈ°λŠ” l × l이닀. 체슀판의 각 칸은 두 수의 쌍 {0, ..., l-1} × {0, ..., l-1}둜 λ‚˜νƒ€λ‚Ό 수 μžˆλ‹€. λ‘˜μ§Έ 쀄과 μ…‹μ§Έ μ€„μ—λŠ” λ‚˜μ΄νŠΈκ°€ ν˜„μž¬ μžˆλŠ” μΉΈ, λ‚˜μ΄νŠΈκ°€ μ΄λ™ν•˜λ €κ³  ν•˜λŠ” 칸이 μ£Όμ–΄μ§„λ‹€.

 

좜λ ₯

각 ν…ŒμŠ€νŠΈ μΌ€μ΄μŠ€λ§ˆλ‹€ λ‚˜μ΄νŠΈκ°€ μ΅œμ†Œ λͺ‡ λ²ˆλ§Œμ— 이동할 수 μžˆλŠ”μ§€ 좜λ ₯ν•œλ‹€.

 

μž…μΆœλ ₯ 예제

μž…λ ₯

3
8
0 0
7 0
100
0 0
30 50
10
1 1
1 1

좜λ ₯

5
28
0

 

λ‚΄ 문제 풀이
let cases = Int(readLine()!)!
var dx = [-2, -1, 1, 2, 2, 1, -1, -2], dy = [1, 2, 2, 1, -1, -2, -2, -1] // λ‚˜μ΄νŠΈμ˜ 이동을 μœ„ν•œ μ’Œν‘œκ°’ λ³€ν™”λŸ‰
var result = [Int]()

// μž…λ ₯된 ν…ŒμŠ€νŠΈ μΌ€μ΄μŠ€μ˜ 수 만큼 반볡
for _ in 0..<cases {
    let n = Int(readLine()!)! // 체슀 λ³΄λ“œ ν•œ λ³€μ˜ 길이
    let start = readLine()!.split(separator: " ").map({Int(String($0))!}) // μ‹œμž‘μ 
    let target = readLine()!.split(separator: " ").map({Int(String($0))!}) // λͺ©μ μ§€
    
    if (start[0], start[1]) == (target[0], target[1]) { result.append(0) } // μ²˜μŒλΆ€ν„° μ‹œμž‘μ κ³Ό λͺ©μ μ§€κ°€ 같을 경우 λ°”λ‘œ result에 0μΆ”κ°€
    else {
        let target_check = (target[0], target[1]) // λͺ©μ μ§€λ₯Ό νŠœν”Œλ‘œ 생성
        var queue = [(start[0], start[1])] // 큐 생성, μ‹œμž‘μ μ„ νŠœν”Œλ‘œ λ§Œλ“€μ–΄μ„œ λ„£μ–΄μ£ΌκΈ°
        var board = Array(repeating: Array(repeating: 0, count: n), count: n) // κ²½λ‘œλ§ˆλ‹€ κ±Έλ¦° μ‹œκ°„μ„ λˆ„μ ν•΄μ£Όλ©΄μ„œ μ²΄ν¬ν•˜κΈ° μœ„ν•œ λ³΄λ“œ λ°°μ—΄
        var arrive = 0 // λͺ©μ μ§€μ— λ„μ°©ν–ˆλŠ”μ§€ μ•ˆν–ˆλŠ”μ§€ μ²΄ν¬ν•˜κΈ° μœ„ν•¨ (0이면 도착x)
        
        var index = 0
        while !queue.isEmpty {
            let (x, y) = queue[index]
            index += 1
            
            for i in 0..<8 {
                let dx = x + dx[i]
                let dy = y + dy[i]
               
                if dx < 0 || dy < 0 || dx >= n || dy >= n || board[dx][dy] != 0 { continue } // μ˜ˆμ™Έ

                board[dx][dy] = board[x][y] + 1 // ν•΄λ‹Ή μžλ¦¬κΉŒμ§€ κ±Έλ¦° μ‹œκ°„ λˆ„μ 
                
                if target_check == (dx, dy) { arrive = board[dx][dy]; break } // νƒμƒ‰ν•œ μžλ¦¬κ°€ λͺ©μ μ§€μ™€ 같을 경우
                queue.append((dx, dy)) // 아닐 경우 큐에 μΆ”κ°€
            }
            
            if arrive != 0 { result.append(arrive); break } // arriveκ°€ 0이 아닐 경우 (λͺ©μ μ§€μ— 도착)
        }
    }
}

print(result.map({String($0)}).joined(separator: "\n"))

πŸ‘‰ bfs 문제둜, λ‚˜μ΄νŠΈκ°€ 이동할 수 μžˆλŠ” λͺ¨λ“  경우의 수λ₯Ό κ³ λ €ν•΄μ£ΌλŠ”κ²Œ 포인트!

  • μ§€κΈˆκΉŒμ§€ ν’€μ—ˆλ˜ bfs λ¬Έμ œλ“€κ³Ό 이 문제의 κ°€μž₯ 큰 차이점은,
    λ‚˜μ΄νŠΈλŠ” μƒν•˜μ’Œμš° νƒμƒ‰μ΄μ•„λ‹ˆλΌ 총 8κ°€μ§€μ˜ 경둜λ₯Ό νƒμƒ‰ν•΄μ€˜μ•Όν•œλ‹€λŠ” 것이닀.
    λ”°λΌμ„œ 그에 λ§žλŠ” μ’Œν‘œ λ³€ν™”λŸ‰μ„ λ„£μ–΄μ„œ dx, dy 배열을 μƒμ„±ν•΄μ£Όμ—ˆλ‹€.
  • μš°μ„  if둜 μ²˜μŒλΆ€ν„° μ‹œμž‘μ κ³Ό λͺ©μ μ§€κ°€ 같을 경우λ₯Ό μ˜ˆμ™Έλ‘œ λΉΌμ£Όμ—ˆλ‹€.
    그리고 κ·Έ μ™Έμ˜ κ²½μš°μ—λŠ” bfs 탐색을 μ‹œμž‘ν–ˆλ‹€.
  • while문으둜 bfs 탐색을 ν•΄μ£Όμ—ˆκ³ , index λ³€μˆ˜λ₯Ό μ΄μš©ν•΄μ„œ 큐λ₯Ό λ‹€λ€˜λ‹€.
    λ‚˜μ΄νŠΈκ°€ 이동할 수 μžˆλŠ” κ²½λ‘œλŠ” 총 8κ°œμ΄λ―€λ‘œ whileλ¬Έ μ•ˆμ˜ for문으둜 8번 λ°˜λ³΅ν•΄μ£Όμ—ˆλ‹€.
  • forλ¬Έμ—μ„œλŠ” dx, dy 배열을 μ΄μš©ν•˜μ—¬ λ‹€μŒ 탐색 μœ„μΉ˜λ₯Ό κ²°μ •ν•˜κ³ , κ·Έ μœ„μΉ˜κ°€ μ μ ˆν•œμ§€ νŒλ‹¨ν–ˆλ‹€.
    κ·Έ μœ„μΉ˜κ°€ λ³΄λ“œ λ°”κΉ₯μ΄κ±°λ‚˜ ν•΄λ‹Ή μœ„μΉ˜μ— 0이 μ•„λ‹Œ 값이 μ €μž₯λ˜μ–΄μžˆλ‹€λ©΄ ν•΄λ‹Ή λ°˜λ³΅μ€ μ’…λ£Œν–ˆλ‹€.
    (λͺ¨λ“  경둜 탐색 μ‹œ ν•΄λ‹Ή μžλ¦¬κΉŒμ§€μ˜ 탐색 λˆ„μ  μ‹œκ°„μ„ μ €μž₯ν–ˆμœΌλ―€λ‘œ, 0이 μ•„λ‹Œ 값이 μ €μž₯λ˜μ–΄μžˆλ‹€λŠ” λœ»μ€ ν•΄λ‹Ή μžλ¦¬λŠ” 이미 νƒμƒ‰ν•œμ μ΄ μžˆλ‹€λŠ” μ˜λ―Έμ΄λ‹€. λ”°λΌμ„œ 쀑볡 탐색을 ν”Όν•˜κΈ° μœ„ν•¨!)
    μ˜ˆμ™Έμ²˜λ¦¬μ—μ„œ 걸리지 μ•Šμ•˜λ‹€λ©΄ λ³΄λ“œ λ°°μ—΄μ˜ ν•΄λ‹Ή μœ„μΉ˜μ— λˆ„μ λœ μ‹œκ°„μ„ μ €μž₯ν•΄μ£Όμ—ˆκ³ ,
    νƒμƒ‰ν•œ μžλ¦¬κ°€ λͺ©μ μ§€μ™€ 같을 κ²½μš°μ—λŠ” arrive λ³€μˆ˜μ— λˆ„μ λœ μ‹œκ°„μ„ λ„£κ³  for문을 μ’…λ£Œν•œλ‹€.
    아직 λͺ©μ μ§€μ— λ„λ‹¬ν•˜μ§€ λͺ»ν–ˆμ„ κ²½μš°μ—λŠ” 큐에 λ‹€μŒ 탐색지λ₯Ό μΆ”κ°€ν•˜κ³  싀행을 κ³„μ†ν•œλ‹€.
  • μœ„μ—μ„œ arrive λ³€μˆ˜μ— λˆ„μ λœ μ‹œκ°„μ΄ μ €μž₯λ˜μ—ˆμ„ κ²½μš°μ—λŠ” arriveκ°€ 0이 μ•„λ‹ˆκ²Œλ˜λ―€λ‘œ
    λͺ©μ μ§€μ— λ„μ°©ν•œκ²ƒμœΌλ‘œ νŒλ‹¨ν•˜κ³ , result 배열에 값을 μΆ”κ°€ν•˜κ³  while문을 μ’…λ£Œν•œλ‹€.

 

πŸ’‘ ν”Όλ“œλ°±
  • μƒν•˜μ’Œμš°κ°€ μ•„λ‹Œ 총 8개 경둜 탐색을 μœ„ν•œ dx, dy 배열을 생성해주렀고 ν•œ λΆ€λΆ„μ—μ„œ 쑰금 μ‹œκ°„μ΄ μ§€μ²΄λ˜μ—ˆκ³ , λ‚˜λ¨Έμ§€λŠ” 이전에 ν’€μ—ˆλ˜ λ¬Έμ œλ“€κ³Ό λΉ„μŠ·ν•΄μ„œ 금방 ν’€μ–΄λ‚Ό 수 μžˆμ—ˆλ‹€.

 


문제

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