๋ฐฑ์ค€ - ์นด๋“œ ์ •๋ ฌํ•˜๊ธฐ(Swift)

2022. 10. 24. 12:48ใ†Algorithm

๋ฐฑ์ค€ - ์นด๋“œ ์ •๋ ฌํ•˜๊ธฐ(Swift)

 

 ๋ฌธ์ œ ์„ค๋ช…

 

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

 

1715๋ฒˆ: ์นด๋“œ ์ •๋ ฌํ•˜๊ธฐ

์ •๋ ฌ๋œ ๋‘ ๋ฌถ์Œ์˜ ์ˆซ์ž ์นด๋“œ๊ฐ€ ์žˆ๋‹ค๊ณ  ํ•˜์ž. ๊ฐ ๋ฌถ์Œ์˜ ์นด๋“œ์˜ ์ˆ˜๋ฅผ A, B๋ผ ํ•˜๋ฉด ๋ณดํ†ต ๋‘ ๋ฌถ์Œ์„ ํ•ฉ์ณ์„œ ํ•˜๋‚˜๋กœ ๋งŒ๋“œ๋Š” ๋ฐ์—๋Š” A+B ๋ฒˆ์˜ ๋น„๊ต๋ฅผ ํ•ด์•ผ ํ•œ๋‹ค. ์ด๋ฅผํ…Œ๋ฉด, 20์žฅ์˜ ์ˆซ์ž ์นด๋“œ ๋ฌถ์Œ๊ณผ 30์žฅ

www.acmicpc.net

 

 ๋‚˜์˜ ํ’€์ด

 

๊ฐ€์žฅ ์ž‘์€ ์ˆซ์ž 2๊ฐœ๋ฅผ ๋ฝ‘์•„์„œ ๋ˆ„์ ์‹œํ‚ค๋ฉด ๋˜๋Š” ๊ฒƒ์€ ์•Œ์•˜์ง€๋งŒ 100,000๊ฐœ์ธ ์ˆซ์ž๋ฅผ sortํ•œ๋‹ค๋Š” ๊ฒƒ์€ ์‹œ๊ฐ„๋ณต์žก๋„๊ฐ€ ๋„ˆ๋ฌด ๋†’์•„์ ธ๋ฒ„๋ฆฐ๋‹ค๋Š” ํ—›์ ์ด ์žˆ์—ˆ๋‹ค.

 

๊ทธ๋ž˜์„œ ๋‹ค๋ฅธ์‚ฌ๋žŒ์˜ ํ’€์ด๋ฅผ ์ฐธ๊ณ ํ•˜์—ฌ ์šฐ์„ ์ˆœ์œ„ ํ๋ฅผ ์ด์šฉํ•ด์„œ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ–ˆ๋‹ค.

์•„๋ž˜ ์ฝ”๋“œ์˜ ์šฐ์„ ์ˆœ์œ„ ํ๋Š” Heap<์ž๋ฃŒํ˜•>(array: ๋ฐฐ์—ด๋ณ€์ˆ˜, sort: ์ •๋ ฌ๋ฐฉํ–ฅ)์œผ๋กœ ์„ ์–ธํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ remove()!์™€ insert๋ฅผ ํ†ตํ•ด์„œ ํž™์„ logN์œผ๋กœ ์‚ฝ์ž…, ์‚ญ์ œ๊ฐ€ ๊ฐ€๋Šฅํ•ด์ง„๋‹ค. 

 

๊ทธ๋ฆฌ๊ณ  ์ด ๋ฌธ์ œ๋Š” n์ด 1์ผ๋•Œ๋Š” ๋น„๊ต๋ฅผ ์•„์˜ˆ ์•ˆํ•˜๊ธฐ ๋•Œ๋ฌธ์— 0์„ ์ถœ๋ ฅํ•˜๋Š” ๊ฒŒ ๋งž๋‹ค. 

 

import Foundation

public struct Heap<T> {
    
    private var nodes = [T]()
    
    private var orderCriteria: (T, T) -> Bool
    
    public init(sort: @escaping (T, T) -> Bool) {
        // ์ตœ๋Œ€ ํž™์ธ์ง€ ์ตœ์†Œ ํž™์ธ์ง€ ๊ธฐ์ค€์„ ์žก๋Š”๋‹ค.
        self.orderCriteria = sort
    }
    
    public init(array: [T], sort: @escaping (T, T) -> Bool) {
        self.orderCriteria = sort
        configureHeap(from: array)
    }
    
    public var count: Int {
        return nodes.count
    }
    
    public func peek() -> T? {
        return nodes.first
    }
    
    public mutating func insert(_ value: T) {
        nodes.append(value)
        shiftUp(nodes.count - 1)
    }
    
    public mutating func remove() -> T? {
        guard !nodes.isEmpty else { return nil }
        
        if nodes.count == 1 {
            return nodes.removeLast()
        } else {
            let value = nodes[0]
            nodes[0] = nodes.removeLast()
            shiftDown(0)
            return value
        }
    }
    
    public mutating func remove(at index: Int) -> T? {
        guard index < nodes.count else { return nil }
        
        let lastIndex = nodes.count-1
        if index != lastIndex {
            nodes.swapAt(index, lastIndex)
            shiftDown(from: index, until: lastIndex)
            shiftUp(index)
        }
        
        return nodes.removeLast()
    }
    
    // ๋ณ€์ˆ˜๋ฅผ ์ง์ ‘ ๋ณ€๊ฒฝํ•ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— mutating ์„ ์‚ฌ์šฉํ•œ๋‹ค.
    private mutating func configureHeap(from array: [T]) {
        nodes = array
        
        /**
         * ํž™ ํŠธ๋ฆฌ์—์„œ n/2 - 1 ์€ ํ•˜๋‚˜ ์œ„ ์ธต์œ„๊ฐ€ ๋œ๋‹ค.
         * shiftDown์„ ํ•˜๋ฉด์„œ ์ž๋ฆฌ๋ฅผ ์žก์„ ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์—
         * ๋งˆ์ง€๋ง‰ leaf ๋…ธ๋“œ๋“ค์€ ํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค.
         */
        for i in stride(from: nodes.count/2 - 1, through: 0, by: -1) {
            shiftDown(i)
        }
    }
    
    private func parentIndex(ofIndex i: Int) -> Int {
        return (i - 1) / 2
    }
    
    private func leftChildIndex(ofIndex i: Int) -> Int {
        return 2*i + 1
    }
    
    private func rightChildIndex(ofIndex i: Int) -> Int {
        return 2*i + 2
    }
    
    /**
     * shiftUp์€ ์ž์‹ ๊ณผ ๋ถ€๋ชจ๋ฅผ ๋น„๊ตํ•ด ๋ฐ”๊ฟ”์ค€๋‹ค.
     */
    private mutating func shiftUp(_ index: Int) {
        var childIndex = index
        let child = nodes[childIndex] // ์ฒ˜์Œ์— ๋…ธ๋“œ๋ฅผ ์ €์žฅํ•ด๋‘๊ณ  ์ธ๋ฑ์Šค๋ฅผ ๊ตฌํ•œ ํ›„ ๋ฐ”๊ฟ”์ค€๋‹ค.
        var parentIndex = self.parentIndex(ofIndex: index)
        
        while childIndex > 0 && orderCriteria(child, nodes[parentIndex]) {
            nodes[childIndex] = nodes[parentIndex]
            childIndex = parentIndex
            parentIndex = self.parentIndex(ofIndex: childIndex)
        }
        
        nodes[childIndex] = child
    }
    
    /**
     * shiftDown์€ left, right ์ž์‹ ์ค‘ ์ ํ•ฉํ•œ ๋…€์„์ด ์žˆ์œผ๋ฉด ๋ฐ”๊พธ๋ฉด์„œ ๋ฐ”๋‹ฅ๊นŒ์ง€ ๋‚ด๋ ค๊ฐ„๋‹ค.
     */
    private mutating func shiftDown(from index: Int, until endIndex: Int) {
        let leftChildIndex = self.leftChildIndex(ofIndex: index)
        let rightChildIndex = leftChildIndex + 1
        
        var first = index
        if leftChildIndex < endIndex && orderCriteria(nodes[leftChildIndex], nodes[first]) {
            first = leftChildIndex
        }
        if rightChildIndex < endIndex && orderCriteria(nodes[rightChildIndex], nodes[first]) {
            first = rightChildIndex
        }
        if first == index { return }
        
        nodes.swapAt(index, first)
        shiftDown(from: first, until: endIndex)
    }
    
    private mutating func shiftDown(_ index: Int) {
        shiftDown(from: index, until: nodes.count)
    }
    
}

let n = Int(readLine()!)!
var numbers: [Int] = []
for _ in 0..<n {
    numbers.append(Int(readLine()!)!)
}
var cost = 0
var heap = Heap<Int>(array: numbers, sort: <)
while heap.count > 1 {
    let a = heap.remove()!
    let b = heap.remove()!
    cost += (a+b)
    heap.insert(a+b)
}
print(cost)

 

 

'Algorithm' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

๋ฐฑ์ค€ A->B(Swift)  (0) 2022.10.24
๋ฐฑ์ค€ - ๋’ค์ง‘๊ธฐ(Swift)  (0) 2022.10.24
๋ฐฑ์ค€ - ์‹ ์ž…์‚ฌ์›(Swift)  (0) 2022.10.24
๋ฐฑ์ค€ - 30(Swift)  (0) 2022.10.24
๋ฐฑ์ค€ - ์ฃผ์œ ์†Œ(Swift)  (0) 2022.10.24