Skip to content

Latest commit

ย 

History

History
950 lines (752 loc) ยท 30.7 KB

gold.md

File metadata and controls

950 lines (752 loc) ยท 30.7 KB
description
๊ทธ๋ž˜ํ”„ํƒ์ƒ‰ ๊ณจ๋“œ ๋ฌธ์ œ

๐Ÿฅ‡ [๊ทธ๋ž˜ํ”„] Gold

1707 ์ด๋ถ„ ๊ทธ๋ž˜ํ”„

๋ฌธ์ œ๋กœ ์ด๋™

๋ฌธ์ œ ์š”์•ฝ

๊ทธ๋ž˜ํ”„์˜ ์ •์  ์ง‘ํ•ฉ์„ ๋‘๊ฐœ๋กœ ๋ถ„ํ• ํ•˜์—ฌ, ๊ฐ ์ง‘ํ•ฉ์— ์†ํ•œ ์ •์ ๋ผ๋ฆฌ๋Š” ์„œ๋กœ ์ธ์ ‘ํ•˜์ง€ ์•Š๋„๋ก ๋ถ„ํ• ํ•  ์ˆ˜ ์žˆ์„ ๋•Œ, ์ด๋ถ„ ๊ทธ๋ž˜ํ”„๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค. ๊ทธ๋ž˜ํ”„๊ฐ€ ์ฃผ์–ด์กŒ์œผ ใ„น๋•Œ, ์ด๋ถ„๊ทธ๋ž˜ํ”„์ธ์ง€ ํŒ๋ณ„ํ•˜๋Š” ํ”„๋กœ๊ทธ๋žจ์„ ์ž‘์„ฑํ•ด์•ผํ•œ๋‹ค.

์•Œ๊ณ ๋ฆฌ์ฆ˜

  1. ์ •๋ณด๋ฅผ ์ž…๋ ฅ๋ฐ›๊ณ , ํ…Œ์ŠคํŠธ์ผ€์ด์Šค๋งŒํผ ๋ฐ˜๋ณตํ•œ๋‹ค.
  2. ๊ทธ๋ž˜ํ”„๋ฅผ ๋ฌด๋ฐฉํ–ฅ ๊ทธ๋ž˜ํ”„๋กœ ์ž…๋ ฅ๋ฐ›๋Š”๋‹ค. (์–‘๋ฐฉํ–ฅ ๊ฐ„์„ )
  3. ์ „์ฒด ๋…ธ๋“œ์— ๋Œ€ํ•ด bfs๋ฅผ ํƒ์ƒ‰ํ•˜๋ฉฐ ์ด๋ถ„ ๊ทธ๋ž˜ํ”„์ธ์ง€ ํŒ๋ณ„ํ•œ๋‹ค.
  4. ๊ฒฐ๊ณผ๋ฅผ ์ถœ๋ ฅํ•œ๋‹ค.

์ ‘๊ทผ๋ฐฉ๋ฒ•

  • ์šฐ์„  ๋‚˜๋Š” ๋ฌธ์ œ๋ฅผ ๋ณด๊ณ  ์ด๋ถ„ ๊ทธ๋ž˜ํ”„์˜ ์ •ํ™•ํ•œ ์ •์˜๋ฅผ ์•Œ์ง€ ๋ชปํ–ˆ๋‹ค. (๊ทธ๋ž˜ํ”„์— ์‚ฌ์ดํด์ด ์žˆ๋Š”๊ฐ€๋ฅผ ํ™•์ธํ•˜๋Š” ๋ฌธ์ œ๊ฐ€ ์•„๋‹ˆ๋ผ๋Š” ๊ฒƒ์ด๋‹ค)
    • ์œ„ํ‚ค์— ์ด๋ถ„ ๊ทธ๋ž˜ํ”„์˜ ์ •์˜๋ฅผ ๋ณด๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋‚˜์™€์žˆ๋‹ค.
    • "๋ชจ๋“  ๊ผญ์ง“์ ์„ ๋นจ๊ฐ•, ํŒŒ๋ž‘์œผ๋กœ ์ƒ‰์น ํ•˜๋˜, ๋ชจ๋“  ๋ณ€์ด ๋นจ๊ฐ•๊ณผ ํŒŒ๋ž‘ ๊ผญ์ง“์ ์„ ํฌํ•จํ•˜๋„๋ก ์ƒ‰์น ํ•  ์ˆ˜ ์žˆ๋‹ค."
    • ์ฆ‰, ใ…‡-ใ…‡ ๋ผ๋Š” ๋‘ ๊ฐœ์˜ ๋…ธ๋“œ๋ฅผ ์—ฐ๊ฒฐํ•˜๋Š” ๊ฐ„์„ ์˜ ์ž…์žฅ์—์„œ ํ•œ ์ชฝ์€ ๋นจ๊ฐ„์ƒ‰, ๋‹ค๋ฅธ ํ•œ ์ชฝ์€ ํŒŒ๋ž€์ƒ‰์œผ๋กœ ์น ํ•  ์ˆ˜ ์žˆ์–ด์•ผํ•œ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค.
    • ์ฝ”๋“œ ๊ด€์ ์œผ๋กœ ์ƒ๊ฐํ•ด๋ณด์ž๋ฉด visited[here]๊ณผ visited[next]์˜ ๊ฐ’์ด ๋‹ฌ๋ผ์•ผํ•จ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค.
  • ์ฃผ์˜ํ•ด์•ผํ•  ์ ์€ ํ•˜๋‚˜์˜ ๊ทธ๋ž˜ํ”„๋กœ ์ฃผ์–ด์ง€์ง€ ์•Š์„ ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค.
    • ์ฆ‰, ์ „์ฒด ๋…ธ๋“œ๋ฅผ ๋ฐฉ๋ฌธํ–ˆ๋Š”์ง€ ํ™•์ธํ•˜๋Š” ์ž‘์—…์ด ํ•„์š”ํ•˜๋‹ค.
    • ๋‚˜๋Š” ํ˜„์žฌ tree์˜ key๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํƒ์ƒ‰ํ•˜๊ณ  ์žˆ๋‹ค. ๊ทธ๋ž˜์„œ ํ…Œ์ŠคํŠธ์ผ€์ด์Šค์—์„œ ๋ฐ˜๋“œ์‹œ ํŠธ๋ฆฌ๋ฅผ ๋นˆ ๋”•์…”๋„ˆ๋ฆฌ๋กœ ํ•œ ๋ฒˆ ์ดˆ๊ธฐํ™”ํ•ด์ฃผ๋Š” ์ž‘์—…์ด ํ•„์š”ํ•˜๋‹ค. (๋˜๋Š” v๋ฅผ ๋”ฐ๋กœ ์ €์žฅํ•ด์„œ bfs๋ฅผ ์ˆ˜ํ–‰ํ•ด๋„ ๊ดœ์ฐฎ๋‹ค)
  • visited๋ฅผ -1๋กœ ์ดˆ๊ธฐํ™”ํ•œ ์ด์œ 
    • ๋‚˜๋Š” ์›๋ž˜ visited[0]์œผ๋กœ ๋ฐฉ๋ฌธํ•˜์ง€ ์•Š์•˜์Œ์„ ํ‘œ๊ธฐํ–ˆ๋‹ค.
    • ์ด์ „๊ณผ๋Š” ๋‹ค๋ฅด๊ฒŒ visited ๋ฐฐ์—ด์— 3๊ฐ€์ง€ ์ •๋ณด๋ฅผ ์ €์žฅํ•ด์•ผํ•œ๋‹ค. (์•„์ง ๋ฐฉ๋ฌธ ์•ˆ ํ•จ, ๋นจ๊ฐ„์ƒ‰, ํŒŒ๋ž€์ƒ‰)
    • ๋‚˜๋Š” ์ด๊ฒƒ์„ -1, 0, 1๋กœ ํ‘œ๊ธฐํ•ด์„œ ๋ชจ๋“ˆ๋Ÿฌ 2๋ฅผ ํ†ตํ•ด here๊ณผ next๋ฅผ ์‰ฝ๊ฒŒ ํ‘œ๊ธฐํ•˜๊ณ ์ž ํ•œ ๊ฒƒ์ด๋‹ค!

์ฝ”๋“œ

let testCase = Int(readLine()!)!
var tree = [Int: [Int]]()
var visited = [Int]()

for _ in 0 ..< testCase {
    var flag = true
    getInformation()
    for node in tree.keys {
        if node == 0 { continue }
        if visited[node] == -1 {
            guard bfs(node) else {
                print("NO")
                flag = false
                break
            }
        }
    }
    if flag { print("YES") }
}

// ๋ฌธ์ œ์—์„œ ์ฃผ์–ด์ง€๋Š” ์ •๋ณด๋ฅผ ์ž…๋ ฅ๋ฐ›์Œ
func getInformation() {
    
    let input = readLine()!.split { $0 == " " }.map { Int($0)! }
    let (v, e) = (input[0], input[1])
    
    tree = [Int: [Int]]() // ์ด๊ฑฐ ์—†์œผ๋ฉด ๋Ÿฐํƒ€์ž„ ์—๋Ÿฌ. (์ด์ „ ํ‚ค ๊ฐ’์ด ํŠธ๋ฆฌ์— ์ €์žฅ๋˜์–ด ์žˆ์Œ)
    Array(0...v).forEach { tree[$0] = [] } // dictionary ์ดˆ๊ธฐํ™”
    
    for _ in 0 ..< e {
        let input = readLine()!.split { $0 == " " }.map { Int($0)! }
        let (u, v) = (input[0], input[1])
        tree[u]!.append(v)
        tree[v]!.append(u)
    }
    
    visited = [Int](repeating: -1, count: v + 1)
}

func bfs(_ n: Int) -> Bool {
    var queue = [n]
    visited[n] = 0
    var index = 0
    
    while queue.count > index {
        let here = queue[index]
        index += 1
        guard let child = tree[here] else { continue }
        for next in child {
        
            // visited[here]๊ณผ visited[next]๊ฐ€ ๊ฐ™๋‹ค๋ฉด ์ด๋ถ„๊ทธ๋ž˜ํ”„๊ฐ€ ์•„๋‹˜
            // here๋Š” ๋ฐฉ๋ฌธ์ฒ˜๋ฆฌ๊ฐ€ ๋˜์–ด์žˆ์œผ๋ฏ€๋กœ -1๊ณผ ๊ฐ™์„ ์ˆ˜ ์—†์Œ
            guard visited[here] != visited[next] else { return false }
            
            // ํ˜„์žฌ ์ƒํ™ฉ์€ here๊ณผ next์˜ visited ๊ฐ’์ด ๋‹ค๋ฅธ ์ƒํ™ฉ์ž„.
            // ์ฆ‰, next๋Š” here๊ณผ ์ƒ‰์ƒ์ด ๋‹ค๋ฅด๊ฑฐ๋‚˜, ์•„์ง ๋ฐฉ๋ฌธํ•˜์ง€ ์•Š์€ ์ƒํ™ฉ
            // ์•„์ง ๋ฐฉ๋ฌธํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ๋งŒ queue์— ์‚ฝ์ž…ํ•œ๋‹ค.
            guard visited[next] == -1 else { continue }
            visited[next] = (visited[here] + 1) % 2
            queue.append(next)
        }
    }
    // ใ…‡-ใ…‡์—์„œ ํ•œ ๋ฒˆ๋„ ๊ฐ™์€ ์ƒ‰์„ ์น ํ•œ ์  ์—†๋‹ค๋ฉด true๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
    return true
}

1753 ์ตœ๋‹จ ๊ฒฝ๋กœ

๋ฌธ์ œ๋กœ ์ด๋™

๋ฌธ์ œ ์š”์•ฝ

๋ฐฉํ–ฅ ๊ทธ๋ž˜ํ”„๊ฐ€ ์ฃผ์–ด์กŒ์„ ๋•Œ, ์‹œ์ž‘ ์ ์—์„œ ๋‹ค๋ฅธ ๋ชจ๋“  ์ •์ ์œผ๋กœ์˜ ์ตœ๋‹จ ๊ฒฝ๋กœ๋ฅผ ๊ตฌํ•˜๋Š” ํ”„๋กœ๊ทธ๋žจ์„ ์ž‘์„ฑํ•ด์•ผํ•œ๋‹ค.

์•Œ๊ณ ๋ฆฌ์ฆ˜

  1. ์ฃผ์–ด์ง„ ๊ทธ๋ž˜ํ”„๋ฅผ ๋”•์…”๋„ˆ๋ฆฌ ํ˜•ํƒœ๋กœ ์ž…๋ ฅ๋ฐ›๋Š”๋‹ค.
  2. Min Heap ์ž๋ฃŒ๊ตฌ์กฐ๋ฅผ ๋งŒ๋“ ๋‹ค. (Swift๋Š” heap ์ž๋ฃŒ๊ตฌ์กฐ๋ฅผ ์ œ๊ณตํ•˜์ง€ ์•Š๋Š”๋‹ค.)
  3. ๋‹ค์ต์ŠคํŠธ๋ผ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์ˆ˜ํ–‰ํ•œ๋‹ค.

์ ‘๊ทผ ๋ฐฉ๋ฒ•

  • ํ•œ ์ •์ ์—์„œ ๋‹ค๋ฅธ ๋ชจ๋“  ์ •์ ์˜ ์ตœ๋‹จ ๊ฒฝ๋กœ๋ฅผ ๊ตฌํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ๋‹ค์ต์ŠคํŠธ๋ผ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์‚ฌ์šฉํ•ด์•ผํ•œ๋‹ค.
  • ์ด์— ์ตœ์†Œ ํž™์„ ์ œ์ž‘ํ•˜์—ฌ ๋‹ค์ต์ŠคํŠธ๋ผ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ๊ตฌํ˜„ํ•ด์•ผํ•œ๋‹ค.

์ฝ”๋“œ

์ตœ์†Œ ํž™ ์ฝ”๋“œ
// ์ตœ์†Œ ํž™ ๊ตฌํ˜„
struct Heap <T: Comparable> {
    var heap = [T]()
    
    private func getParent(_ index: Int) -> T {
        heap[index / 2]
    }
    
    private func getLeftChild(_ index: Int) -> T {
        heap[index * 2]
    }
    
    private func getRightChild(_ index: Int) -> T {
        heap[index * 2 + 1]
    }
    
    func isEmpty() -> Bool {
        heap.count <= 1
    }
    
    mutating func push(_ data: T) {
        if isEmpty() { heap.append(data) }
        var index = heap.count
        heap.append(data)
        
        while index > 1 {
            let parent = getParent(index)
            guard parent > data else { break }
            heap[index] = parent
            index /= 2
        }
        heap[index] = data
    }
    
    mutating func pop() -> T? {
        guard !isEmpty() else { return nil }
        let item = heap[1]
        let data = heap.removeLast()
        let size = heap.count - 1
        
        guard !isEmpty() else { return item }
        var (parent, child) = (1, 2)
        while child <= size {
            if child < size && getLeftChild(parent) > getRightChild(parent) {
                child += 1
            }
            guard data > heap[child] else { break }
            heap[parent] = heap[child]
            parent = child
            child *= 2
        }
        heap[parent] = data
        return item
    }
}
struct Node: Comparable {
    static func < (lhs: Node, rhs: Node) -> Bool {
        lhs.cost < rhs.cost
    }
    
    init(_ node: Int, _ cost: Int) {
        self.node = node
        self.cost = cost
    }
    
    let node: Int
    let cost: Int
}

let input = readLine()!.split { $0 == " " }.map { Int($0)! }, (v, e) = (input[0], input[1])
let start = Int(readLine()!)!
var graph = [Int: [Node]]()
var result = [Int](repeating: Int.max, count: v+1)
for i in 1...v { 
    graph[i] = []
}

for _ in 0 ..< e {
    let input = readLine()!.split { $0 == " " }.map { Int($0)! }
    let (start, end, cost) = (input[0], input[1], input[2])
    graph[start]!.append(Node(end, cost))
}

dijkstra(start)
for i in 1...v {
    print(result[i] == Int.max ? "INF" : result[i])
}

func dijkstra(_ start: Int) {
    var queue = Heap<Node>()
    var visited = [Bool](repeating: false, count: v + 1)
    result[start] = 0
    queue.push((Node(start, 0)))
    
    while let current = queue.pop() {
        let (node, cost) = (current.node, current.cost)
        guard !visited[node] else { continue }
        visited[node] = true
        if let edge = graph[node] {
            for next in edge {
                let (nextNode, nextCost) = (next.node, next.cost)
                guard !visited[nextNode] else { continue }
                let newCost = cost + nextCost
                if newCost < result[nextNode] {
                    result[nextNode] = newCost
                    queue.push(Node(nextNode, newCost))
                }
            }
        }
    }
}

1916 ์ตœ์†Œ๋น„์šฉ ๊ตฌํ•˜๊ธฐ

๋ฌธ์ œ๋กœ ์ด๋™

๋ฌธ์ œ ์š”์•ฝ

N๊ฐœ์˜ ๋„์‹œ๊ฐ€ ์žˆ๋‹ค. ํ•œ ๋„์‹œ์—์„œ ์ถœ๋ฐœํ•˜์—ฌ, ๋‹ค๋ฅธ ๋„์‹œ์— ๋„์ฐฉํ•˜๋Š” M๊ฐœ์˜ ๋ฒ„์Šค๊ฐ€ ์žˆ์„ ๋•Œ, A ๋„์‹œ์—์„œ B ๋„์‹œ๋กœ ๊ฐ€๋Š” ์ตœ์†Œ ๋น„์šฉ์„ ์ถœ๋ ฅํ•ด๋ผ.

์•Œ๊ณ ๋ฆฌ์ฆ˜

  1. ์ตœ์†Œ ํž™์„ ๊ตฌํ˜„ํ•œ๋‹ค. (์Šค์œ„ํ”„ํŠธ๋„ ํž˜ ์ค˜์„œ ํž™ ๋‚ด๋†”๋ผ)
  2. ์ฃผ์–ด์ง„ ์ •๋ณด๋ฅผ ์ž…๋ ฅ๋ฐ›๋Š”๋‹ค.
    1. ๋„์‹œ์˜ ๊ฐœ์ˆ˜๋ฅผ ์ž…๋ ฅ ๋ฐ›๋Š”๋‹ค. (๋”•์…”๋„ˆ๋ฆฌ์˜ ํ‚ค์˜ ๊ฐœ์ˆ˜๊ฐ€ ๋œ๋‹ค.)
    2. ๋ฒ„์Šค์˜ ๊ฐœ์ˆ˜๋ฅผ ์ž…๋ ฅ ๋ฐ›๋Š”๋‹ค. (๊ฐ„์„ ์˜ ๊ฐœ์ˆ˜๊ฐ€ ๋œ๋‹ค.)
    3. city[์‹œ์ž‘๋…ธ๋“œ] = [ (๋„์ฐฉ๋„์‹œ, ๋น„์šฉ)] ์œผ๋กœ ๋”•์…”๋„ˆ๋ฆฌ๋ฅผ ์ž…๋ ฅ๋ฐ›๋Š”๋‹ค. (์ด๋•Œ ๊ฐ์ฒด๋Š” ๋น„์šฉ์„ ๊ธฐ์ค€์œผ๋กœ ์ •๋ ฌ๋˜์–ด์•ผ ํ•œ๋‹ค)
  3. ๋‹ค์ต์ŠคํŠธ๋ผ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์ˆ˜ํ–‰ํ•œ๋‹ค.
  4. ๋„์ฐฉ ๋„์‹œ์— ๋Œ€ํ•œ ๋น„์šฉ์„ ์ถœ๋ ฅํ•œ๋‹ค.

์ ‘๊ทผ๋ฐฉ๋ฒ•

  • ์ „ํ˜•์ ์ธ ๋‹ค์ต์ŠคํŠธ๋ผ ๋ฌธ์ œ๋กœ ํ’€ ์ˆ˜ ์žˆ๋‹ค.
  • ํŠน์ • ๋…ธ๋“œ์—์„œ ๋‹ค๋ฅธ ๋…ธ๋“œ๋กœ ๊ฐ€๋Š”๋ฐ์— ์ตœ์†Œ ๋น„์šฉ์„ ๊ตฌํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

์ฝ”๋“œ

์ตœ์†Œ ํž™ ์ฝ”๋“œ
struct Heap<T: Comparable> {
    var heap = [T]()
    
    private func isEmpty() -> Bool {
        heap.count <= 1
    }
    
    private func getParent(_ index: Int) -> T {
        heap[index / 2]
    }
    
    private func getLeftChild(_ index: Int) -> T {
        heap[index * 2]
    }
    
    private func getRightChild(_ index: Int) -> T {
        heap[index * 2 + 1]
    }
    
    mutating func push(_ data: T) {
        if isEmpty() { heap.append(data) }
        var index = heap.count
        heap.append(data)
        
        while index > 1 {
            let parent = getParent(index)
            guard parent > data else { break }
            heap[index] = parent
            index /= 2
        }
        heap[index] = data
    }
    
    mutating func pop() -> T? {
        guard !isEmpty() else { return nil }
        let item = heap[1]
        let last = heap.removeLast()
        let size = heap.count - 1
        
        guard !isEmpty() else { return item }
        
        var (parent, child) = (1, 2)
        
        while child <= size {
            if size > child, getLeftChild(parent) > getRightChild(parent) {
                    child += 1
            }
            
            if last <= heap[child] { break }
            heap[parent] = heap[child]
            parent = child
            child *= 2
        }
        heap[parent] = last
        return item
    }
}
// ํž™์— ๋„ฃ์„ ๋„์‹œ ๊ตฌ์กฐ์ฒด์ด๋‹ค. ๊ฐ์ฒด ๊ฐ„ ํฌ๊ธฐ๋Š” cost(๋น„์šฉ)์œผ๋กœ ๊ฒฐ์ •๋œ๋‹ค.
struct City: Comparable {
    static func < (lhs: City, rhs: City) -> Bool {
        lhs.cost < rhs.cost
    }
    
    init(_ city: Int, _ cost: Int) {
        self.city = city
        self.cost = cost
    }
    
    let city: Int
    let cost: Int
}

let n = Int(readLine()!)! // ๋„์‹œ์˜ ๊ฐœ์ˆ˜
let m = Int(readLine()!)! // ๋ฒ„์Šค์˜ ๊ฐœ์ˆ˜
var city = [Int: [City]]()
Array(1...n).forEach { city[$0] = [] } // ์‚ฝ์ž… ์‹œ ํŽธ๋ฆฌํ•จ์„ ์œ„ํ•ด ๋„์‹œ ์ •๋ณด๋ฅผ ์ดˆ๊ธฐํ™”ํ•œ๋‹ค.

for _ in 0 ..< m {
    let input = readLine()!.split { $0 == " " }.map { Int($0)! }
    let (start, end, cost) = (input[0], input[1], input[2])
    city[start]!.append(City(end, cost))
}

let input = readLine()!.split { $0 == " " }.map { Int($0)! }
let (startCity, endCity) = (input[0], input[1])
var costs = [Int](repeating: Int.max, count: n + 1)

dijkstra()
print(costs[endCity])

// ๋‹ค์ต์ŠคํŠธ๋ผ ์•Œ๊ณ ๋ฆฌ์ฆ˜
func dijkstra() {
    var visited = [Bool](repeating: false, count: n+1)
    var queue = Heap<City>()
    costs[startCity] = 0
    queue.push(City(startCity, 0))
    
    while let current = queue.pop() {
        let (currentCity, currentCost) = (current.city, current.cost)
        guard !visited[currentCity] else { continue }
        visited[currentCity] = true
        
        if let edges = city[currentCity] {
            for city in edges {
                let (nextCity, nextCost) = (city.city, city.cost)
                guard !visited[nextCity] else { continue }
                
                let newCost = currentCost + nextCost
                if costs[nextCity] > newCost {
                    costs[nextCity] = newCost
                    queue.push(City(nextCity, newCost))
                }
            }
        }
    }
}

2206 ๋ฒฝ ๋ถ€์ˆ˜๊ณ  ์ด๋™ํ•˜๊ธฐ

๋ฌธ์ œ๋กœ ์ด๋™

๋ฌธ์ œ ์š”์•ฝ

N * M ํ–‰๋ ฌ๋กœ ํ‘œํ˜„๋˜๋Š” ๋งต์ด ์žˆ๋‹ค. 0์€ ์ด๋™ํ•  ์ˆ˜ ์žˆ๋Š” ๊ธธ์ด๊ณ  1์€ ์ด๋™ํ•  ์ˆ˜ ์—†๋Š” ๋ฒฝ์ด๋ฉฐ ์ƒํ•˜์ขŒ์šฐ๋กœ ์ด๋™ํ•  ์ˆ˜ ์žˆ๋‹ค. (1, 1)์—์„œ (N, M)๊นŒ์ง€ ์ตœ๋‹จ๊ฑฐ๋ฆฌ๋กœ ์ด๋™ํ•ด์•ผํ•œ๋‹ค. ์ด๋™ ๊ฑฐ๋ฆฌ๋Š” ์‹œ์ž‘ํ•˜๋Š” ์นธ๊ณผ ๋๋‚˜๋Š” ์นธ๋„ ํฌํ•จ๋˜์–ด์•ผํ•˜๋ฉฐ, ์ด๋™ ์ค‘ ๋ฒฝ์„ ํ•œ ๊ฐœ ๊นŒ์ง€ ๋ถ€์ˆ˜๊ณ  ์ด๋™ํ•  ์ˆ˜ ์žˆ๋‹ค.

์•Œ๊ณ ๋ฆฌ์ฆ˜

  1. ๋งต์„ ์ž…๋ ฅ๋ฐ›๋Š”๋‹ค. (์‹œ๊ฐ„์ดˆ๊ณผ ์ฃผ์˜)
  2. 3์ฐจ์›์˜ visited ๋ฐฐ์—ด์„ ์„ ์–ธํ•œ๋‹ค.
  3. bfs๋ฅผ ์ˆ˜ํ–‰ํ•œ๋‹ค.

์ ‘๊ทผ๋ฐฉ๋ฒ•

  • ์‹œ๊ฐ„์ดˆ๊ณผ ๋•Œ๋ฌธ์— ์‚ฝ์งˆ ์–ด์–ด์–ด์–ด์–ด์–ด์–ด์—„์ฒญ ํ•œ ๋ฌธ์ œ์ด๋‹ค.
  • ์ฒซ ๋ฒˆ์งธ ์ ‘๊ทผ - (์•ˆ ๋  ๊ฑฐ ๋ป”ํ•˜์ง€๋งŒ, ๋ฌด์‹ํ•˜๊ฒŒ ํ’€์–ด๋ณด์ž)
    • ์ง€๋„๋ฅผ ์ž…๋ ฅ๋ฐ›์„ ๋•Œ, walls๋ผ๋Š” ๋ฒฝ์˜ ์œ„์น˜๋ฅผ ๋ชจ๋‘ ์ž…๋ ฅ๋ฐ›์€ ํ›„, ๋ชจ๋“  ๊ฒฝ์šฐ์˜ ์ˆ˜๋ฅผ ํƒ์ƒ‰ํ•˜๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค.
    • N, M์˜ ๋ฒ”์œ„๊ฐ€ ์ตœ๋Œ€ 1,000์ด๋ฏ€๋กœ $$O(N^2)$$ -> 1,000,000,000,000์„ ํ›Œ์ฉ.. ๋„˜๋Š”๋‹ค!
    • ๋„ˆ๋ฌด ๋‹น์—ฐํžˆ ์‹œ๊ฐ„์ดˆ๊ณผ
  • N ๋ฒˆ์งธ ์ ‘๊ทผ - 3์ฐจ์›์˜ visited ๋ฐฐ์—ด์„ ์‚ฌ์šฉํ•œ๋‹ค. (๋‹ค๋ฅธ ์‚ฌ๋žŒ๋“ค์˜ ์•„์ด๋””์–ด๋ฅผ ์ฐธ๊ณ ํ–ˆ๋‹ค.. ๋‹ค์„ฏ์‹œ๊ฐ„ ๊ณ ๋ฏผํ•จ ใ…Ž)
    • visited[n][m][2]๋ฅผ ํ†ตํ•ด์„œ ์ด์ œ๊นŒ์ง€ ๋ฒฝ์„ ๋ถ€์ˆœ ์  ์žˆ์Œ?์„ ํ™•์ธํ•˜๋Š”๊ฒŒ ํ•ต์‹ฌ ์•„์ด๋””์–ด๋‹ค.
    • Swift๋Š” 3์ฐจ์› ๋ฐฐ์—ด ์•„์ด๋””์–ด๋งŒ์œผ๋กœ ์ด ๋ฌธ์ œ๋ฅผ ํ’€ ์ˆ˜ ์—†๋‹ค. ์‹œ๊ฐ„์ดˆ๊ณผ๊ฐ€ ๋ฐœ์ƒํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ์šฐ๋ฆฌ๋Š” ์ž๋ฃŒ๊ตฌ์กฐ์— ๋” ์‹ ๊ฒฝ์„ ์จ์ค˜์•ผ๋œ๋‹ค.
      • ๊ธฐ๋ณธ์ ์œผ๋กœ ์ด์ œ๊นŒ์ง€ ์‚ฌ์šฉํ–ˆ๋˜ Queue.removeFirst๋Š” O(n)์ด ์†Œ์š”๋œ๋‹ค.
      • ๊ทธ๋ž˜์„œ ์ด removeFirst๋ฅผ ๋ฐ”๊ฟ”์ค˜์•ผํ•˜๋Š”๋ฐ, ๋‚˜๋Š” ๋‘ ๊ฐ€์ง€ ์‹œ๋„๋ฅผ ํ–ˆ๋‹ค.
        • (์‹คํŒจ) Queue.reverse -> Queue.removeLast() -> Queue.reverse

          Swift์˜ reverse()๊ฐ€ O(1)์ด๊ธฐ ๋•Œ๋ฌธ์— ์ „ํ˜€ ๋ฌธ์ œ๋˜์ง€ ์•Š์„๊ฑฐ๋ผ ์ƒ๊ฐํ–ˆ๋Š”๋ฐ, ์‹œ๊ฐ„์ดˆ๊ณผ๊ฐ€ ๋‚ฌ๋‹ค.. ใ…Ž

        • (์„ฑ๊ณต) Index๋ฅผ ์ด์šฉํ•˜์—ฌ Queue๋ฅผ ํƒ์ƒ‰ํ•˜๋Š” ๋ฐฉ๋ฒ•

          Queue.count > index๋ฅผ while๋ฌธ์˜ ์กฐ๊ฑด์œผ๋กœ ๋„ฃ๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค.

          ์•ž์œผ๋กœ๋Š” ์ด ๋ฐฉ๋ฒ•์„ ์  ๊ทน ํ™œ ์šฉ ํ•ด์•ผ๊ฒ ๋‹ค. ใ… ใ… ใ… ใ… ใ… ใ… ใ… 

์ฝ”๋“œ

// ์ด๋™ ๊ฐ€๋Šฅ ๋ฐฉํ–ฅ ์ •์˜
let dy = [-1, 1, 0, 0]
let dx = [0, 0, 1, -1]

let input = readLine()!.split { $0 == " " }.map { Int(String($0))! }, (n, m) = (input[0], input[1])
var map = [[Bool]]()
var visited = [[[Bool]]](repeating: [[Bool]](repeating: [false, false], count: m), count: n)

for _ in 0 ..< n {
    let input = readLine()!.map { $0 == "0" ? true : false }
    map.append(input)
}

print(bfs())

func bfs() -> Int {
    var queue = [(0, 0, 0, 1)] // (y, x, wall, count)
    visited[0][0][0] = true
    if (n, m) == (1, 1) { return 1 } // ์‹œ์ž‘์œ„์น˜๊ฐ€ ์ข…๋ฃŒ์œ„์น˜๋ผ๋ฉด 1์„ ๋ฐ˜ํ™˜
    
    var index = 0 // ์‹œ๊ฐ„์ดˆ๊ณผ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•
    while queue.count > index {
        let (y, x, wall, count) = queue[index]
        index += 1
        
        for i in 0 ..< 4 {
            let ny = dy[i] + y
            let nx = dx[i] + x
            
            // ๋งต ๋ฒ”์œ„ ๋‚ด์— ์กด์žฌํ•˜๊ณ , ์•„์ง ๋ฐฉ๋ฌธํ•˜์ง€ ์•Š์•˜๋‹ค๋ฉด
            guard 0 ..< n ~= ny && 0 ..< m ~= nx && !visited[ny][nx][wall] else { continue }
            
            // ๋ชฉ์ ์ง€์— ๋„์ฐฉํ–ˆ๋‹ค๋ฉด ๊ฒฐ๊ณผ ๋ฆฌํ„ด
            if (ny, nx) == (n-1, m-1) { return count + 1 }
            
            // map์ด true๋ผ๋ฉด (๊ธธ) ๋ฐฉ๋ฌธ์ฒ˜๋ฆฌ ํ›„ queue์— ์‚ฝ์ž…ํ•œ๋‹ค.
            if map[ny][nx] {
                visited[ny][nx][wall] = true
                queue.append((ny, nx, wall, count + 1))
                
            // map์ด false์ด๊ณ , ์•„์ง๊นŒ์ง€ ๋ฒฝ์„ ๋ถ€์ˆœ ์  ์—†๋‹ค๋ฉด
            } else if wall == 0 {
                // ๋ฒฝ ๋ถ€์ˆœ ์œ„์น˜์— visited ์ฒ˜๋ฆฌ
                visited[ny][nx][1] = true
                // ์–˜๋กœ๋ถ€ํ„ฐ ์ถœ๋ฐœํ•˜๋Š” ๋‹ค์Œ ์œ„์น˜๋ถ€ํ„ฐ๋Š” wall์— 1์ด ์ €์žฅ๋œ๋‹ค.
                queue.append((ny, nx, 1, count + 1))
            }
        }
    }
    // ๋ชฉ์ ์ง€๋ฅผ ์ฐพ์ง€ ๋ชปํ–ˆ๋‹ค๋ฉด
    return -1
}
์‹œ๊ฐ„์ดˆ๊ณผ ์ฝ”๋“œ ๋ณด๊ธฐ (์™„์ „ํƒ์ƒ‰)
let dy = [-1, 0, 1, 0]
let dx = [0, 1, 0, -1]

let input = readLine()!.split { $0 == " " }.map { Int($0)! }, (n, m) = (input[0], input[1])
var map = [[Int]]()
var walls = [(Int, Int)]()
var visited = [[Int]](repeating: [Int](repeating: 0, count: m), count: n)
var result = Int.max

for y in 0 ..< n {
    let input = readLine()!.map { Int(String($0))! }
    for x in 0 ..< m {
        if input[x] == 1 {
            walls.append((y, x))
        }
    }
    map.append(input)
}

result = bfs(0, 0)

for (y, x) in walls {
    map[y][x] = 0
    result = min(result, bfs(0, 0))
    map[y][x] = 1
}

print(result == Int.max ? -1 : result)

func bfs(_ y: Int, _ x: Int) -> Int {
    var queue = [(y, x)]
    visited[y][x] = 1
    
    while !queue.isEmpty {
        let (y, x) = queue.removeFirst()
        for i in 0 ..< 4 {
            let ny = dy[i] + y
            let nx = dx[i] + x
            
            guard 0 ..< n ~= ny && 0 ..< m ~= nx && map[ny][nx] == 0 else { continue }
            let next = visited[y][x] + 1
            guard visited[ny][nx] == 0 || next < visited[ny][nx] else { continue }
            if (ny, nx) == (n-1, m-1) {
                return next
            }
            visited[ny][nx] = next
            queue.append((ny, nx))
        }
    }
    return Int.max
}

7576 ํ† ๋งˆํ† 

๋ฌธ์ œ๋กœ ์ด๋™

๋ฌธ์ œ ์š”์•ฝ

์ฐฝ๊ณ ์— ํ† ๋งˆํ† ๊ฐ€ ๋ณด๊ด€๋˜์–ด์žˆ๋‹ค. ๋ณด๊ด€ ํ›„ ํ•˜๋ฃจ๊ฐ€ ์ง€๋‚˜๋ฉด, ์ต์ง€ ์•Š์€ ํ† ๋งˆํ† ๋Š” ์ธ์ ‘ํ•ด์žˆ๋Š” ์ต์€ํ† ๋งˆํ† ์˜ ์˜ํ–ฅ์„ ๋ฐ›์•„ ํ•˜๋ฃจ๊ฐ€ ์ง€๋‚˜๋ฉด ์ต๊ฒŒ ๋œ๋‹ค. (ํ† ๋งˆํ† ๊ฐ€ ํ˜ผ์ž ์ €์ ˆ๋กœ ์ต๋Š” ๊ฒฝ์šฐ๋Š” ์—†๋‹ค) ํ† ๋งˆํ† ๊ฐ€ ๋ฉฐ์น ์ด ์ง€๋‚˜ ๋‹ค ์ต๊ฒŒ ๋˜๋Š”์ง€, ์ตœ์†Œ ์ผ ์ˆ˜๋ฅผ ๊ตฌํ•ด๋ผ. (1์€ ์ต์€ ํ† ๋งˆํ† , 0์€ ์ต์ง€ ์•Š์€ ํ† ๋งˆํ† , -1์€ ํ† ๋งˆํ† ๊ฐ€ ์—†๋Š” ์นธ์ด๋‹ค)

์•Œ๊ณ ๋ฆฌ์ฆ˜

  1. ์ฃผ์–ด์ง„ ํ† ๋งˆํ†  ์ •๋ณด๋ฅผ ์ž…๋ ฅ๋ฐ›๋Š”๋‹ค.
    1. ์ด๋•Œ, ํ† ๋งˆํ† ๊ฐ€ ์ž…๋ ฅ ๋œ ๊ฒฝ์šฐ, tomato๋ผ๋Š” ๋ฐฐ์—ด์— ๋„ฃ๋Š”๋‹ค.
  2. ์ž…๋ ฅ๋ฐ›์€ ํ† ๋งˆํ†  ํ๋ฅผ ์ด์šฉํ•˜์—ฌ bfs๋ฅผ ์ˆ˜ํ–‰ํ•œ๋‹ค.
  3. ํ† ๋งˆํ†  ์ƒ์ž์— 0์ด ์žˆ๋Š” ๊ฒฝ์šฐ๋งŒ ์ต๋Š”๋‹ค๊ณ  ์ƒ๊ฐํ•˜๋ฉด ๋œ๋‹ค.(์ด๋™ํ•œ๋‹ค)
  4. ๊ฒฐ๊ณผ๋ฅผ ์ถœ๋ ฅํ•œ๋‹ค.
    1. ํ† ๋งˆํ†  ์ƒ์ž๋ฅผ ์กฐํšŒํ•˜๋ฉฐ 0์ด ํ•˜๋‚˜๋ผ๋„ ์žˆ๋‹ค๋ฉด -1์„ ์ถœ๋ ฅํ•œ๋‹ค.
    2. ํ† ๋งˆํ†  ์ƒ์ž์˜ ์ตœ๋Œ“๊ฐ’์„ ์ถœ๋ ฅํ•œ๋‹ค.

์ ‘๊ทผ๋ฐฉ๋ฒ•

  • ์ฒ˜์Œ์—๋Š” ๋ชจ๋“  ์‹œ์ž‘ ํ† ๋งˆํ† ์— ๋Œ€ํ•ด ๊ฐ๊ฐ bfs๋ฅผ ์ˆ˜ํ–‰ํ•ด์•ผํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ–ˆ๋‹ค.
  • ํ•˜์ง€๋งŒ ์‹œ์ž‘ queue์— ๋ชจ๋“  ํ† ๋งˆํ† ๋ฅผ ๋„ฃ๊ณ  ์‹คํ–‰ํ•ด๋„ depth๋ณ„๋กœ ์‹คํ–‰๋˜๊ธฐ ๋•Œ๋ฌธ์— ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ์ฆ‰ bfs ํ•œ ๋ฒˆ๋งŒ์œผ๋กœ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์Œ์„ ์˜๋ฏธํ•œ๋‹ค.
    • ์ด๋•Œ queue์— ๊ธฐ์กด bfs์ฒ˜๋Ÿผ (0,0)์ด ์•„๋‹ˆ๋ผ ๋ชจ๋“  ํ† ๋งˆํ†  ๋ฐฐ์—ด์ด ๋“ค์–ด๊ฐ„๋‹ค๋ฉด ๊ฐ€๋Šฅํ•˜๋‹ค!
  • ์‹œ๊ฐ„์ดˆ๊ณผ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•
    • ์šฐ์„  Swift์—์„œ queue๋Š” ๋งค์šฐ ์‰ฝ๊ฒŒ ๊ตฌํ˜„ํ•  ์ˆœ ์žˆ๋‹ค. (removeFirst๋ฅผ ์ง€์›ํ•˜๋‹ˆ๊นŒ)
    • ํ•˜์ง€๋งŒ RemoveFirst๋Š” ์‹œ๊ฐ„๋ณต์žก๋„ O(n)์ด ์†Œ์š”๋œ๋‹ค!!
    • ์—ฌ๋Ÿฌ๊ฐ€์ง€ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์ด ์žˆ๋‹ค.
      • ๋ฐฐ์—ด์˜ ์ธ๋ฑ์Šค๋ฅผ ์ด์šฉํ•˜์—ฌ pop ๋œ ๊ฒƒ ์ฒ˜๋Ÿผ ์‚ฌ์šฉํ•œ๋‹ค. (๋‚ด๊ฐ€ ์ฑ„ํƒํ•œ ๋ฐฉ๋ฒ•)
      • reverse() -> removeFirtst() -> reverse()๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. (reverse๋Š” O(1)์ด๋‹ค)
      • ์‹ค์ œ ํ ๊ตฌํ˜„ํ•˜๊ธฐ ๋“ฑ ์—ฌ๋Ÿฌ๊ฐ€์ง€๊ฐ€ ์žˆ๋‹ค.

์ฝ”๋“œ

let input = readLine()!.split { $0 == " " }.map { Int($0)! }, (m, n) = (input[0], input[1])
var map = [[Int]]()
var tomato = [(Int, Int)]()

// ์ •๋ณด๋ฅผ ์ž…๋ ฅ๋ฐ›๋Š”๋‹ค. ๋‹จ, ํ† ๋งˆํ† ์ธ ๊ฒฝ์šฐ ๋”ฐ๋กœ ๋ฐฐ์—ด์— ์ €์žฅํ•œ๋‹ค.
for y in 0 ..< n {
    let input = readLine()!.split { $0 == " " }.map { Int($0)! }
    for x in 0 ..< m {
        if input[x] == 1 {
            tomato.append((y, x))
        }
    }
    map.append(input)
}

bfs()
print(getResult())

func bfs() {
    let dy = [-1, 0, 1, 0]
    let dx = [0, 1, 0, -1]
    var index = 0
    
    // ํ† ๋งˆํ†  ๋ฐฐ์—ด์„ ์ด์šฉํ•˜์—ฌ bfs๋ฅผ ์ˆ˜ํ–‰ํ•œ๋‹ค.
    while tomato.count > index {
        let (y, x) = tomato[index]
        index += 1
        
        for i in 0 ..< 4 {
            let ny = dy[i] + y
            let nx = dx[i] + x
            
            guard 0..<n ~= ny && 0..<m ~= nx && map[ny][nx] == 0 else { continue }
            map[ny][nx] = map[y][x] + 1
            tomato.append((ny, nx))
        }
    }
}

func getResult() -> Int {
    var result = 0
    for t in map {
        if t.contains(0) { return -1 }
        result = max(result, t.max()!)
    }
    return result - 1
}

16236 ์•„๊ธฐ์ƒ์–ด

๋ฌธ์ œ๋กœ ์ด๋™

๋ฌธ์ œ ์š”์•ฝ

N*N ๊ณต๊ฐ„์— ๋ฌผ๊ณ ๊ธฐ M๋งˆ๋ฆฌ์™€ ์•„๊ธฐ ์ƒ์–ด 1๋งˆ๋ฆฌ๊ฐ€ ์žˆ๋‹ค. ์•„๊ธฐ์ƒ์–ด๋Š” ์ƒ, ํ•˜, ์ขŒ, ์šฐ๋กœ ์›€์ง์ผ ์ˆ˜ ์žˆ๋‹ค. ์ด๋•Œ, ์ž๊ธฐ๋ณด๋‹ค ๋ชธ์ง‘์ด ํฐ ๋ฌผ๊ณ ๊ธฐ๋Š” ์ง€๋‚˜๊ฐˆ ์ˆ˜ ์—†๊ณ , ๋ชธ์ง‘์ด ๊ฐ™์€ ๋ฌผ๊ณ ๊ธฐ๋Š” ์ง€๋‚˜๊ฐˆ ์ˆ˜ ์žˆ๋‹ค. ๋ฌผ๊ณ ๊ธฐ๊ฐ€ ์ž๊ธฐ๋ณด๋‹ค ๋ชธ์ง‘์ด ์ž‘๋‹ค๋ฉด, ๋จน์„ ์ˆ˜ ์žˆ๋Š”๋ฐ ์ž๊ธฐ ํฌ๊ธฐ ๋งŒํผ ๋ฌผ๊ณ ๊ธฐ๋ฅผ ๋จน์œผ๋ฉด 1๋งŒํผ ์•„๊ธฐ ์ƒ์–ด์˜ ๋ชธ์ง‘์ด ์ปค์ง„๋‹ค. ์ด๋•Œ, ์ƒ์–ด๊ฐ€ ๋ช‡ ์ดˆ ๋™์•ˆ ์—„๋งˆ์—๊ฒŒ ๋„์›€์„ ์š”์ฒญํ•˜์ง€ ์•Š๊ณ  ๋ฌผ๊ณ ๊ธฐ๋ฅผ ์žก์•„๋จน์„ ์ˆ˜ ์žˆ๋Š”์ง€ ๊ณ„์‚ฐํ•ด๋ผ.

  • ์•„๊ธฐ์ƒ์–ด๋Š” ๋” ์ด์ƒ ๋จน์„ ์ˆ˜ ์žˆ๋Š” ๋ฌผ๊ณ ๊ธฐ๊ฐ€ ๊ณต๊ฐ„์— ์—†๋‹ค๋ฉด, ์—„๋งˆ์ƒ์–ด์—๊ฒŒ ๋„์›€์„ ์š”์ฒญํ•œ๋‹ค.
  • ๋จน์„ ์ˆ˜ ์žˆ๋Š” ๋ฌผ๊ณ ๊ธฐ๊ฐ€ 1๋งˆ๋ฆฌ๋ผ๋ฉด, ๊ทธ ๋ฌผ๊ณ ๊ธฐ๋ฅผ ๋จน์œผ๋Ÿฌ ๊ฐ„๋‹ค.
  • ๋จน์„ ์ˆ˜ ์žˆ๋Š” ๋ฌผ๊ณ ๊ธฐ๊ฐ€ 1๋งˆ๋ฆฌ๋ณด๋‹ค ๋งŽ๋‹ค๋ฉด, ๊ฑฐ๋ฆฌ๊ฐ€ ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ๋ฌผ๊ณ ๊ธฐ๋ฅผ ๋จน์œผ๋Ÿฌ ๊ฐ„๋‹ค.
    • ๊ฑฐ๋ฆฌ๋Š” ์•„๊ธฐ ์ƒ์–ด๊ฐ€ ์ง€๋‚˜๊ฐ€์•ผํ•˜๋Š” ์นธ์˜ ์ตœ์†Œ ๊ฐœ์ˆ˜์ด๋‹ค.
    • ๊ฑฐ๋ฆฌ๊ฐ€ ๊ฐ€๊นŒ์šด ๋ฌผ๊ณ ๊ธฐ๊ฐ€ ๋งŽ๋‹ค๋ฉด, ๊ฐ€์žฅ ์œ„์— ์žˆ๋Š” ๋ฌผ๊ณ ๊ธฐ, ๊ทธ๋Ÿฌํ•œ ๋ฌผ๊ณ ๊ธฐ๊ฐ€ ๋งŽ๋‹ค๋ฉด ๊ฐ€์žฅ ์™ผ์ชฝ์— ์žˆ๋Š” ๋ฌผ๊ณ ๊ธฐ๋ฅผ ๋จน๋Š”๋‹ค.

์•Œ๊ณ ๋ฆฌ์ฆ˜

  1. n์„ ์ž…๋ ฅ๋ฐ›๋Š”๋‹ค.
  2. ์ง€๋„ ์ •๋ณด๋ฅผ ์ž…๋ ฅ๋ฐ›๋Š”๋‹ค.
    1. ์ž…๋ ฅ ๊ฐ’์— 9๊ฐ€ ์žˆ๋‹ค๋ฉด ์ƒ์–ด์˜ ์œ„์น˜๋ฅผ ์ €์žฅํ•˜๊ณ , ํ•ด๋‹น map์„ 0์œผ๋กœ ์ดˆ๊ธฐํ™”ํ•œ๋‹ค.
    2. ์ž…๋ ฅ ๊ฐ’์ด ๋ฌผ๊ณ ๊ธฐ๋ผ๋ฉด, ๋ฌผ๊ณ ๊ธฐ ์ง‘ํ•ฉ์— ์ •๋ณด๋ฅผ ์ถ”๊ฐ€ํ•œ๋‹ค.
  3. bfs๊ฐ€ 0์„ ๋ฆฌํ„ดํ•  ๋•Œ๊นŒ์ง€ bfs๋ฅผ ์ˆ˜ํ–‰ํ•œ๋‹ค.
    1. ๋ฌผ๊ณ ๊ธฐ ์ง‘ํ•ฉ์ด ๋น„์–ด์žˆ๋‹ค๋ฉด 0์„ ๋ฆฌํ„ดํ•œ๋‹ค. (์ข…๋ฃŒ์กฐ๊ฑด 1)
    2. flood fill ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์ˆ˜ํ–‰ํ•˜์—ฌ depth ๋ณ„๋กœ ๋„ˆ๋น„ ์šฐ์„  ํƒ์ƒ‰์„ ์ˆ˜ํ–‰ํ•œ๋‹ค.
    3. ๋‹ค์Œ ์œ„์น˜๊ฐ€ ๋ฌผ๊ณ ๊ธฐ๋ผ๋ฉด ์ž„์‹œ ๋ฌผ๊ณ ๊ธฐ ๋ฐฐ์—ด์— ์ €์žฅํ•˜๊ณ , ์•„๋‹ˆ๋ผ๋ฉด ๊ณ„์† ํƒ์ƒ‰์„ ์ˆ˜ํ–‰ํ•œ๋‹ค.
    4. ๊ฐ™์€ depth์˜ ํƒ์ƒ‰์ด ๋๋‚˜๋ฉด ์ž„์‹œ ๋ฌผ๊ณ ๊ธฐ ๋ฐฐ์—ด์— ๋ฌผ๊ณ ๊ธฐ๊ฐ€ ์žˆ๋Š”์ง€ ํ™•์ธํ•œ๋‹ค. (์—†๋‹ค๋ฉด ๊ณ„์† bfs ์ˆ˜ํ–‰)
    5. ๋งŒ์•ฝ ์ž„์‹œ ๋ฌผ๊ณ ๊ธฐ ๋ฐฐ์—ด์— ๋ฌผ๊ณ ๊ธฐ๊ฐ€ ์žˆ๋‹ค๋ฉด ์กฐ๊ฑด์— ๋งž๋Š” ๋ฌผ๊ณ ๊ธฐ๋ฅผ ๋จน์œผ๋Ÿฌ ๊ฐ€์•ผํ•œ๋‹ค.
      1. ์ž„์‹œ ๋ฌผ๊ณ ๊ธฐ ๋ฐฐ์—ด์„ ์ •๋ ฌํ•œ๋‹ค. (์ขŒ์ƒ๋‹จ ๋ฌผ๊ณ ๊ธฐ ์ฐพ๊ธฐ)
      2. ์ „์—ญ์— ์žˆ๋Š” ๋ฌผ๊ณ ๊ธฐ ์ง‘ํ•ฉ์—์„œ ๋จน์„ ๋ฌผ๊ณ ๊ธฐ๋ฅผ ์ œ์™ธํ•œ๋‹ค.
      3. ์ด์ œ ๋ฌผ๊ณ ๊ธฐ๊ฐ€ ์—†์œผ๋ฏ€๋กœ ํ•ด๋‹น ์œ„์น˜๋ฅผ 0์œผ๋กœ ์ดˆ๊ธฐํ™”ํ•œ๋‹ค.
      4. ๋จน์€ ๋ฌผ๊ณ ๊ธฐ๋ฅผ +1 ํ•ด์ค€๋‹ค. (์ƒ์–ด ์ปค์ง€๋Š” ์กฐ๊ฑด)
    6. map์„ ๋ชจ๋‘ ์กฐํšŒํ–ˆ๋‹ค๋ฉด 0์„ ๋ฆฌํ„ดํ•œ๋‹ค. (์ข…๋ฃŒ์กฐ๊ฑด 2)

์ ‘๊ทผ ๋ฐฉ๋ฒ•

  • ๊ณ ๋ฏผํ•ด์•ผํ•˜๋Š” ๋ถ€๋ถ„
    • dy, dx์˜ ๋ฐฉํ–ฅ๋งŒ์œผ๋กœ ์กฐ๊ฑด์„ ์„ฑ๋ฆฝํ•  ์ˆ˜ ์—†๋‹ค! -> flood fill ์‚ฌ์šฉ (๋งค์šฐ ์ค‘์š”)
      • ๋ฌด์กฐ๊ฑด ๊ฐ™์€ depth์—์„œ ๋จน์„ ์ˆ˜ ์žˆ๋Š” ๋ฌผ๊ณ ๊ธฐ๋ฅผ ํ™•์ธํ•œ ํ›„ ์ •๋ ฌ์„ ์ˆ˜ํ–‰ํ•ด์ค˜์•ผํ•œ๋‹ค. (๋ฐฑ์ค€์งˆ๋ฌธ)
    • ๋ฌผ๊ณ ๊ธฐ๋ฅผ ๋จน์„ ์ˆ˜ ์—†๋Š” ์ƒํ™ฉ
      • ๋‚จ์€ ๋ฌผ๊ณ ๊ธฐ๋“ค์ด ์ „๋ถ€ ๋‹ค ํฌ๊ธฐ๊ฐ€ ์ƒ์–ด๋ณด๋‹ค ํฌ๊ฑฐ๋‚˜ ๊ฐ™์€ ๊ฒฝ์šฐ
      • ๋‚˜๋ณด๋‹ค ์ž‘์€ ๋ฌผ๊ณ ๊ธฐ๊ฐ€ ์žˆ์ง€๋งŒ, ํฐ ๋ฌผ๊ณ ๊ธฐ๋“ค์ด ๋ง‰๊ณ  ์žˆ์–ด์„œ ๋จน์ง€ ๋ชปํ•˜๋Š” ๊ฒฝ์šฐ
        • ์ด ๊ฒฝ์šฐ๊ฐ€ ๊ต‰์žฅํžˆ ์ค‘์š”ํ•˜๋‹ค.
        • return์€ ๋ฌผ๊ณ ๊ธฐ๋ฅผ ๋จน์€ ์ƒํ™ฉ์—์„œ๋งŒ ํ•ด์ค˜์•ผ๋œ๋‹ค. (์ด๋™ํ•œ ํ›„์— ๋ฌผ๊ณ ๊ธฐ๋ฅผ ๋จน์ง€ ๋ชปํ•œ ์ƒํ™ฉ์—์„œ depth๋ฅผ ๋ฆฌํ„ด์‹œํ‚ค๋ฉด ํ‹€๋ฆฐ ๋‹ต์ด ๋‚˜์˜จ๋‹ค)
  • ์ƒ์–ด ํฌ๊ธฐ ์ •์˜ ๋ฐฉ๋ฒ•
    • Swift์˜ didSet์„ ์‚ฌ์šฉํ•˜๋ฉด ๊น”๋”ํ•˜๊ฒŒ ์“ธ ์ˆ˜ ์žˆ๋‹ค!

์ฝ”๋“œ

// ๋ฌผ๊ณ ๊ธฐ ์ž๋ฃŒํ˜•
struct Fish: Hashable {
    let y: Int
    let x: Int
    var size: Int
}

let n = Int(readLine()!)!
var map = [[Int]]()
var sharkX = 0, sharkY = 0
var fishes = Set([Fish]())
var sharkSize = 2
var ateFish = 0 { // ์ƒ์–ด ํฌ๊ธฐ ์ •์˜
    didSet {
        if ateFish == sharkSize {
            sharkSize += 1
            ateFish = 0
        }
    }
}

// ์ฃผ์–ด์ง„ ์ •๋ณด๋ฅผ ์ž…๋ ฅ๋ฐ›๋Š”๋‹ค.
// ์ƒ์–ด์˜ ๊ฒฝ์šฐ, ์œ„์น˜๋งŒ ์ €์žฅํ•˜๊ณ , map์—๋Š” 0์„ ์ €์žฅํ•ด์ค€๋‹ค.
// ๋ฌผ๊ณ ๊ธฐ์˜ ๊ฒฝ์šฐ ์ง‘ํ•ฉ์— ๋„ฃ์–ด์ฃผ์ž.
for y in 0 ..< n {
    var input = readLine()!.split { $0 == " " }.map { Int($0)! }
    for x in 0 ..< n {
        let size = input[x]
        switch size {
        case 0: break
        case 9:
            (sharkY, sharkX) = (y, x)
            input[x] = 0
        default: fishes.insert(Fish(y: y, x: x, size: size))
        }
    }
    map.append(input)
}

var result = 0
while true {
    let count = bfs(sharkY, sharkX)
    result += count
    if count == 0 {
        print(result)
        break
    }
}

func bfs(_ y: Int, _ x: Int) -> Int {
    let dy = [-1, 0, 1, 0]
    let dx = [0, 1, 0, -1]        
    var visited = [[Bool]](repeating: [Bool](repeating: false, count: n), count: n)
    visited[y][x] = true
    var queue = [(y, x)]
    var count = 0 // ์ด๋™ ๊ฑฐ๋ฆฌ
    var fish = [Fish]() // ํ˜„์žฌ depth์—์„œ ๋จน์„ ์ˆ˜ ์žˆ๋Š” ๋ฌผ๊ณ ๊ธฐ ์ง‘ํ•ฉ
    
    if fishes.isEmpty { return 0 } // ๋จน์„ ์ˆ˜ ์žˆ๋Š” ๋ฌผ๊ณ ๊ธฐ๊ฐ€ ์—†๋‹ค๋ฉด 0์„ ๋ฆฌํ„ด (์ข…๋ฃŒ์กฐ๊ฑด1)
    
    while !queue.isEmpty {
        count += 1
        let depth = queue.count // flood fill
        for _ in 0 ..< depth {
            let (y, x) = queue.removeFirst()
            
            for i in 0 ..< 4 {
                let ny = dy[i] + y
                let nx = dx[i] + x
                
                guard 0 ..< n ~= ny && 0 ..< n ~= nx else { continue }
                guard !visited[ny][nx] && map[ny][nx] <= sharkSize else { continue }
                visited[ny][nx] = true
                
                let next = map[ny][nx]
                if [0, sharkSize].contains(next) { // ์ด๋™ํ•˜๋Š” ๊ฒฝ์šฐ
                    queue.append((ny, nx))
                } else {                            // ๋ฌผ๊ณ ๊ธฐ๋ฅผ ๋จน์„ ์ˆ˜ ์žˆ๋Š” ๊ฒฝ์šฐ
                    fish.append(Fish(y: ny, x: nx, size: next))
                }
            }
        }
        
        // ์ด๋ฒˆ depth์—์„œ ๋ฌผ๊ณ ๊ธฐ๋ฅผ ๋จน์„ ์ˆ˜ ์žˆ๋‹ค๋ฉด
        if !fish.isEmpty {
            // ์กฐ๊ฑด์— ๋งž๋Š” ๋ฌผ๊ณ ๊ธฐ๋ฅผ ์ฐพ๋Š”๋‹ค.
            fish = fish.sorted { $0.x < $1.x }.sorted { $0.y < $1.y }
            let shark = fish[0]
            
            // ๋ฌผ๊ณ ๊ธฐ ๋ฐฐ์—ด์—์„œ ํ•ด๋‹น ๋ฌผ๊ณ ๊ธฐ๋ฅผ ์ง€์šด๋‹ค.
            fishes.remove(shark)
            
            // ์ƒ์–ด์˜ ์œ„์น˜๋ฅผ ์—…๋ฐ์ดํŠธํ•œ๋‹ค.
            (sharkY, sharkX) = (shark.y, shark.x)
            
            // ์ง€๋„์— 0์œผ๋กœ ์ €์žฅํ•œ๋‹ค.
            map[sharkY][sharkX] = 0
            
            // ๋ฌผ๊ณ ๊ธฐ ์ˆ˜๋ฅผ ์ถ”๊ฐ€ํ•œ๋‹ค.
            ateFish += 1
            
            // ์ด์ œ๊นŒ์ง€ ์ด๋™ํ•œ ๊ฑฐ๋ฆฌ๋ฅผ ๋ฆฌํ„ดํ•œ๋‹ค.
            return count
        }
    }
    // ๋ชจ๋“  ์ง€๋„๋ฅผ ํƒ์ƒ‰ํ–ˆ์Œ์—๋„ ๋ฌผ๊ณ ๊ธฐ๋ฅผ ๋จน์ง€ ๋ชปํ–ˆ๋‹ค(์ข…๋ฃŒ์กฐ๊ฑด2)
    return 0
}

์ž˜๋ชป๋œ ์ ‘๊ทผ 1 - ํฌ๊ธฐ๊ฐ€ ํฐ ๋ฌผ๊ณ ๊ธฐ๋„ ์ง€๋‚˜๊ฐˆ ์ˆ˜ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ–ˆ๋‹ค (๋ฌธ์ œ๋ฅผ ์ž˜ ์ฝ์ž)

๋ฌธ์ œ๋ฅผ ์ž˜ ์ฝ์–ด์•ผํ•˜๋Š” ์ด์œ ๋‹ค.

์ƒ์–ด๋ณด๋‹ค ๋ชธ์ง‘์ด ํฐ ๊ฒฝ์šฐ๋„ ์›€์ง์ผ ์ˆ˜ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ด์„œ ๋‹จ์ˆœ distance๋ฅผ ๊ตฌํ•ด์„œ ๋ฌธ์ œ๋ฅผ ํ’€์—ˆ์—ˆ๋‹ค...

// ๋ฌผ๊ณ ๊ธฐ ๊ตฌ์กฐ์ฒด
struct Fish: Hashable {
    var y: Int
    var x: Int
    var size: Int
    
    init(_ y: Int, _ x: Int, _ size: Int) {
        self.y = y
        self.x = x
        self.size = size
    }
}

let dy = [-1, 0, 1, 0]
let dx = [0, 1, 0, -1]

let n = Int(readLine()!)!
var fishes = Set([Fish]())
var shark = Fish(0, 0, 0)
var (count, result) = (0, 0)

// ๋ฌผ๊ณ ๊ธฐ ์ •๋ณด ์ž…๋ ฅ๋ฐ›๊ธฐ
for y in 0 ..< n {
    let input = readLine()!.split { $0 == " " }.map { Int(String($0))! }
    for x in 0 ..< n {
        if input[x] == 9 {
            shark = Fish(y, x, 2)
        } else if input[x] != 0 {
            fishes.insert(Fish(y, x, input[x]))
        }
    }
}

while true {
    if count == shark.size {
        count = 0
        shark.size += 1
    }
    // ์กฐ๊ฑด์— ๋”ฐ๋ผ ์ •๋ ฌ
    var foodFish = Array(fishes).filter { $0.size < shark.size }
        .sorted { $0.x < $1.x }
        .sorted { $0.y < $1.y }
        .sorted {
            calculateDistance($0, shark) < calculateDistance($1, shark)
        }
    guard !foodFish.isEmpty else { break }
    let nextFish = foodFish.removeFirst()
    fishes.remove(nextFish)
    count += 1
    
    result += calculateDistance(shark, nextFish)
    (shark.y, shark.x) = (nextFish.y, nextFish.x)   
}
print(result)

// ๋‘ ๋ฌผ๊ณ ๊ธฐ ์‚ฌ์ด์˜ ๊ฑฐ๋ฆฌ ๊ณ„์‚ฐ
func calculateDistance(_ shark: Fish, _ fish: Fish) -> Int {
    abs(shark.x - fish.x) + abs(shark.y + fish.y)
}
์ž˜๋ชป๋œ ์ ‘๊ทผ2 - ๋‹จ์ˆœ bfs๋กœ ํ’€ ์ˆ˜ ์—†๋Š” ์ด์œ 

์ด๊ฑฐ ๋Œ๋ ค๋ณด๋ฉด ์•„๋งˆ ์˜ˆ์ œ 4๋ฒˆ์—์„œ 56์ด ๋‚˜์˜ฌ ๊ฒƒ์ด๋‹ค.. (์—„์ฒญ๋‚œ ์‚ฝ์งˆ)

// ์ƒ์ขŒ์šฐํ•˜๋กœ ํƒ์ƒ‰
let dy = [-1, 0, 0, 1]
let dx = [0, -1, 1, 0]

let n = Int(readLine()!)!
let initialVisited = [[Int]](repeating: [Int](repeating: 0, count: n), count: n)
var visited = initialVisited
var map = [[Int]]()
var shark = (0, 0)
var sharkSize = 2
var result = 0
var ateFish = 0 {
    didSet {
        if ateFish == sharkSize {
            ateFish = 0
            sharkSize += 1
        }
    }
}

for y in 0 ..< n {
    let input = readLine()!.split { $0 == " " }.map { Int($0)! }
    for x in 0 ..< n {
        if input[x] == 9 {
            shark = (y, x)
        }
    }
    map.append(input)
}
map[shark.0][shark.1] = 0
bfs()
print(result)

func bfs() {
    var queue = [shark]
    visited[shark.0][shark.1] = 1
    
    while !queue.isEmpty {
        
        let (y, x) = queue.removeFirst()
        for i in 0 ..< 4 {
            let ny = y + dy[i]
            let nx = x + dx[i]
            
            guard 0 ..< n ~= ny && 0 ..< n ~= nx else { continue }
            guard visited[ny][nx] == 0 && map[ny][nx] <= sharkSize else { continue }
            visited[ny][nx] = visited[y][x] + 1
            queue.append((ny, nx))
            if map[ny][nx] != 0 && map[ny][nx] < sharkSize {
                ateFish += 1
                result += visited[y][x]
                queue = [(ny, nx)]
                visited = initialVisited
                visited[ny][nx] = 1
                map[ny][nx] = 0
                print(ny, nx, result, sharkSize)
                break
            }
        }
    }
}