Swift) 백준 19237번 어른 상어 -G2

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

 

19237번: 어른 상어

첫 줄에는 N, M, k가 주어진다. (2 ≤ N ≤ 20, 2 ≤ M ≤ N2, 1 ≤ k ≤ 1,000) 그 다음 줄부터 N개의 줄에 걸쳐 격자의 모습이 주어진다. 0은 빈칸이고, 0이 아닌 수 x는 x번 상어가 들어있는 칸을 의미

www.acmicpc.net

상어의 현재 방향에 따라 방향의 우선순의가 다르고 격자안에 상어의 냄새에 따라 우선순의가 정해지므로, 이를 구조체로 정의해서 품.

각 상어의 우선순위 방향은 Dictionary로 정의해서 저장

import Foundation

struct shark {
    
    enum Direction: Int {
        case on = 1
        case under
        case left
        case right
    }
    
    let num: Int
    var direction: Direction
    let priorityDirection: [Direction:[Direction]]
    var i: Int
    var j: Int
}

struct Smell {
    var life: Int
    let sharkNum: Int
}

struct CustomSharkArr {
    var arr: [shark] = []
    
    mutating func insert(shark: shark) {
        for arrshark in arr.enumerated() {
            if arrshark.element.i == shark.i && arrshark.element.j == shark.j {
                if shark.num < arrshark.element.num {
                    arr.remove(at: arrshark.offset)
                    arr.append(shark)
                    return
                } else {
                    return
                }
            }
        }
        arr.append(shark)
    }
}

let nmk = readLine()!.split(separator: " ").map{ Int($0)! }
let n = nmk[0]
let m = nmk[1]
let k = nmk[2]
var map: [[Smell?]] = []
var sharkArr: [shark] = []
var sharkCoordi: [(Int, Int)] = Array(repeating: (0,0), count: m)
let di = [-1, 1, 0, 0]
let dj = [0, 0, -1, 1]

for i in 0..<n {
    let input = readLine()!.split(separator: " ").map{ Int($0)! }.enumerated()
    var mapBlock: [Smell?] = []
    for j in input {
        if j.element != 0 {
            sharkCoordi[j.element-1] = (i, j.offset)
            mapBlock.append(.init(life: k, sharkNum: j.element))
        } else {
            mapBlock.append(nil)
        }
    }
    map.append(mapBlock)
}
let sharkDirection = readLine()!.split(separator: " ").map{ Int($0)! }.map{ shark.Direction(rawValue: $0)! }

for i in 0..<m {
    var priorityDir: [shark.Direction:[shark.Direction]] = [:]
    for j in 1...4 {
        let input = readLine()!.split(separator: " ").map{ Int($0)! }.map{ shark.Direction(rawValue: $0)! }
        priorityDir[.init(rawValue: j)!] = input
    }
    let newShark = shark(num: i+1, direction: sharkDirection[i], priorityDirection: priorityDir, i: sharkCoordi[i].0, j: sharkCoordi[i].1)
    sharkArr.append(newShark)
}

func movingShark() {
    
    func checkNoSmellBlock(i:Int, j: Int) -> Bool {
        for x in 0..<4 {
            let mi = i+di[x]
            let mj = j+dj[x]
            if mi < 0 || mi >= n || mj < 0 || mj >= n {
                continue
            }
            if map[mi][mj] == nil {
                return true
            }
        }
        return false
    }
    
    var movingSharkCoordi = CustomSharkArr()
    for shark in sharkArr {
        //인접한 블록에서 냄새가 없는 블록이 있는지 테크
        if checkNoSmellBlock(i: shark.i, j: shark.j) {
            //냄새가 없는 블록이 있으므로 우선순위에 따라 탐색
            let priorityDirection = shark.priorityDirection[shark.direction]
            for i in 0..<4 {
                let mi = shark.i+di[priorityDirection![i].rawValue-1]
                let mj = shark.j+dj[priorityDirection![i].rawValue-1]
                if mi < 0 || mi >= n || mj < 0 || mj >= n {
                    continue
                }
                if map[mi][mj] == nil {
                    var movingshark = shark
                    movingshark.i = mi
                    movingshark.j = mj
                    movingshark.direction = priorityDirection![i]
                    movingSharkCoordi.insert(shark: movingshark)
                    break
                }
            }
        } else {
            //주변에 냄새 없는 블록이 없다면 자신의 냄새가 나는 칸으로
            let priorityDirection = shark.priorityDirection[shark.direction]
            for i in 0..<4 {
                let mi = shark.i+di[priorityDirection![i].rawValue-1]
                let mj = shark.j+dj[priorityDirection![i].rawValue-1]
                if mi < 0 || mi >= n || mj < 0 || mj >= n {
                    continue
                }
                if map[mi][mj]?.sharkNum == shark.num {
                    var movingshark = shark
                    movingshark.direction = priorityDirection![i]
                    movingshark.i = mi
                    movingshark.j = mj
                    movingSharkCoordi.insert(shark: movingshark)
                    break
                }
            }
        }
    }
    sharkArr = movingSharkCoordi.arr
    
}

func applyMap() {
    for i in 0..<n {
        for j in 0..<n {
            map[i][j]?.life -= 1
            if map[i][j]?.life == 0 {
                map[i][j] = nil
            }
        }
    }
    for shark in sharkArr {
        map[shark.i][shark.j] = .init(life: k, sharkNum: shark.num)
    }
}


func solution() -> Int {
    for i in 0...1000 {
        if sharkArr.count == 1 {
            return i
        }
        movingShark()
        applyMap()
    }
    return -1
}

print(solution())