KWiOS
KWiOS0101
KWiOS
  • 분류 전체보기 (108)
    • Algorithm (41)
      • 이코테 (14)
      • 이코테 문제풀이 (21)
      • 프로그래머스 (6)
    • CS (1)
      • 모두를 위한 컴퓨터 과학(CS50 2019) (0)
    • iOS (15)
    • Swift (36)
      • Swift문법 (32)
      • 기타 (4)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • 6

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
KWiOS

KWiOS0101

최소경로 - 전보
Algorithm/이코테 문제풀이

최소경로 - 전보

2022. 8. 13. 18:07
본 내용은 '이것이 취업을 위한 코딩테스트다 with 파이썬' 책을 기반으로 포스팅 하였습니다.

 

문제

저작권 문제가 될 수 있어 문제는 삭제합니다.

 

풀이 코드

class Heap<T: Comparable> {
    var heapArray: [[T]]
    var root: T? {
        if isMaxHeap {
            maxHeapify()
        } else {
            minHeapify()
        }
        return heapArray[0].first
    }
    var count: Int {
        return heapArray.count
    }
    var isEmpty: Bool {
        return heapArray.isEmpty
    }
    var isMaxHeap: Bool

    init(_ n: [[T]], isMaxHeap: Bool) {
        heapArray = n
        self.isMaxHeap = isMaxHeap
    }
    func isLeftChildExist(_ parent: Int) -> Bool {
        if parent * 2 + 1 >= count {
            return false
        } else {
            return true
        }
    }
    func isRightChildExist(_ parent: Int) -> Bool {
        if parent * 2 + 2 >= count {
            return false
        } else {
            return true
        }
    }
    func parentIndex(_ child: Int) -> Int {
        return child / 2
    }
    func leftChildIndex(_ parent: Int) -> Int {
        return parent * 2 + 1
    }
    func rightChildIndex(_ parent: Int) -> Int {
        return parent * 2 + 2
    }
    func maxHeapify() {
        isMaxHeap = true
        var i = count / 2
        while i >= 0 {
            var bigChild: Int = 0
            if isLeftChildExist(i) && isRightChildExist(i) {

                if heapArray[leftChildIndex(i)].first! <= heapArray[rightChildIndex(i)].first! {
                    bigChild = rightChildIndex(i)
                } else {
                    bigChild = leftChildIndex(i)
                }
            } else if isLeftChildExist(i) && !isRightChildExist(i) {
                bigChild = leftChildIndex(i)
            } else if !isLeftChildExist(i) && !isRightChildExist(i) {
                i -= 1
                continue
            }

            if heapArray[bigChild].first! >= heapArray[i].first! {
                let temp = heapArray[bigChild]
                heapArray[bigChild] = heapArray[i]
                heapArray[i] = temp
            }
            i -= 1
        }
    }
    func minHeapify() {
        isMaxHeap = false
        var i = count / 2
        while i >= 0 {
            var smallChild: Int = 0
            if isLeftChildExist(i) && isRightChildExist(i) {
                if heapArray[leftChildIndex(i)].first! >= heapArray[rightChildIndex(i)].first! {
                    smallChild = rightChildIndex(i)
                } else {
                    smallChild = leftChildIndex(i)
                }
            } else if isLeftChildExist(i) && !isRightChildExist(i) {
                smallChild = leftChildIndex(i)
            } else if !isLeftChildExist(i) && !isRightChildExist(i) {
                i -= 1
                continue
            }

            if heapArray[smallChild].first! <= heapArray[i].first! {
                let temp = heapArray[smallChild]
                heapArray[smallChild] = heapArray[i]
                heapArray[i] = temp
            }
            i -= 1
        }
    }
    func popRoot() -> [T]?{
        if isMaxHeap {
            maxHeapify()
        } else {
            minHeapify()
        }
        if !heapArray.isEmpty {
            let temp = heapArray[heapArray.count - 1]
            heapArray[heapArray.count - 1] = heapArray[0]
            heapArray[0] = temp
        }
        let rootValue = heapArray.popLast()

        return rootValue
    }
    func push(_ n: [T]) {
        heapArray.append(n)
    }
}

// -------------------------------------------------------------------------------------
// 문제 풀이 코드

// 노드의 개수, 간선의 개수, 시작노드 입력 받기
let input = readLine()!.components(separatedBy: " ").map({Int($0)!})
// 노드의 개수
let n = input[0]
// 간선의 개수
let m = input[1]
// 시작 노드
let start = input[2]
// 각 노드에 연결되어 있는 노드에 대한 정보를 저장할 배열 초기화
var graph = Array(repeating: [[Int]](), count: n+1)
// 최단 거리 정보를 저장할 배열을 모두 9999999999(무한)으로 초기화
var dp = Array(repeating: 9999999999, count: n+1)

// 모든 간선 정보 입력받기
// input[0] = 메시지 보내는 도시
// input[1] = 메시지 받을 도시 
// input[2] = 메시지를 보내는데 걸리는 시간
// 특정도시 = [걸린시간, 받을 도시]
for _ in 0..<m {
    let input = readLine()!.components(separatedBy: " ").map({Int($0)!})
    graph[input[0]].append(contentsOf: [[input[2], input[1]]])
}


func dijkstra() {

    // 큐 배열 초기화(최소 힙)
    let heap = Heap.init([[Int]](), isMaxHeap: false)

    // 시작노드로 가기위한 최단 경로를 0으로 초기화 후 큐에 삽입
    // [걸리는시간, 시작위치]
    heap.push([0, start])
    // 시작노드 최소거리 배열 초기화
    dp[start] = 0
    
    // 큐가 비어있지 않으면 반복
    while !heap.heapArray.isEmpty {
        // 큐에 저장되어 있는 정보중 최단거리가 가장 짧은 노드에 대한 정보 꺼내기 [보내는데 걸린 시간, 받을 도시]
        let dist = heap.popRoot()!
        let now = dist[1]
        
        // 현재 노드의 비용이 큐에서 꺼낸 정보의 비용보다 작다면 다음 반복 수행
        if dp[now] < dist.first! {
            continue
        }
        
        // 현재 노드와 연결되어 있는 다른 노드들을 확인
        for i in graph[now] {
            // 큐에서 꺼낸 정보의 비용 + 보내는데 걸린 비용 
            let cost = dist.first! + i[0]
            
            // 현재 노드를 거쳐서, 다른 노드로 이동하는 거리가 더 짧으면
            if cost < dp[i[1]] {
                // 현재 노드를 거쳐가는 노드에 cost 저장
                dp[i[1]] = cost
                // 큐에 [보내는데 걸린 시간, 현재 노드를 거쳐가는 노드번호] 삽입
                heap.push([cost, i[1]])
            }
        }
    }
    
    // 메시지를 받을는 도시를 카운트할 변수 선언
    var count = 0
    // 모든 메시지를 받는 데까지 걸리는 시간을 저장할 변수 선언
    var maxDist = 0
    
    for d in dp {
        if d != 9999999999 {
            count += 1
            maxDist = max(maxDist, d)
        }
    }
    print(count - 1, maxDist)
}

dijkstra()

 

문제 풀이

 

 

'Algorithm > 이코테 문제풀이' 카테고리의 다른 글

최소경로 - 미래 도시  (0) 2022.08.13
다이나믹 프로그래밍 - 효율적인 화폐 구성(Swift)  (0) 2022.08.09
다이나믹 프로그래밍 - 바닥 공사(Swift)  (0) 2022.08.09
다이나믹 프로그래밍 - 개미 전사(Swift)  (0) 2022.08.09
다이나믹 프로그래밍 - 1로 만들기(Swift)  (0) 2022.08.09
    'Algorithm/이코테 문제풀이' 카테고리의 다른 글
    • 최소경로 - 미래 도시
    • 다이나믹 프로그래밍 - 효율적인 화폐 구성(Swift)
    • 다이나믹 프로그래밍 - 바닥 공사(Swift)
    • 다이나믹 프로그래밍 - 개미 전사(Swift)
    KWiOS
    KWiOS

    티스토리툴바