Algorithm/Baekjoon
[Swift] 1916 최소비용 구하기
내일은개발천재🎵
2023. 3. 24. 17:20
1916 최소비용 구하기
문제 요약
N개의 도시가 있다. 한 도시에서 출발하여, 다른 도시에 도착하는 M개의 버스가 있을 때, A 도시에서 B 도시로 가는 최소 비용을 출력해라.
알고리즘
- 최소 힙을 구현한다. (스위프트도 힘 줘서 힙 내놔라)
- 주어진 정보를 입력받는다.
- 도시의 개수를 입력 받는다. (딕셔너리의 키의 개수가 된다.)
- 버스의 개수를 입력 받는다. (간선의 개수가 된다.)
- city[시작노드] = [ (도착도시, 비용)] 으로 딕셔너리를 입력받는다. (이때 객체는 비용을 기준으로 정렬되어야 한다)
- 다익스트라 알고리즘을 수행한다.
- 도착 도시에 대한 비용을 출력한다.
접근방법
- 전형적인 다익스트라 문제로 풀 수 있다.
- 특정 노드에서 다른 노드로 가는데에 최소 비용을 구하기 때문이다.
코드
최소 힙 코드
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))
}
}
}
}
}