알고리즘

[Swift 알고리즘] 백준 2343 기타 레슨

코코종 2023. 4. 27. 14:21
728x90

안녕하세요 코코종입니다.

오늘도 이진탐색으로 돌아왔습니다~~

50%에서 런타임에러가 발생하는 바람에... 고생을 좀 했습니다 껄껄...

//
//  main.swift
//  BackJoon
//
//  Created by kokojong on 2023/04/27.
//

import Foundation
// 백준 2343 기타 레슨

let input = readLine()!.split(separator: " ").map { Int(String($0))! }
let n = input[0]
let m = input[1]

let arr = readLine()!.split(separator: " ").map { Int(String($0))! }
let maxV = arr.reduce(0, +)

func binarySearch(l: Int, r: Int) {
    var l = l
    var r = r
    
    while l < r {
        let mid = (l + r) / 2 // 블루레이의 크기
        
        var cnt = 0 // 블루레이의 갯수 (m과 같아야함)
        var sum = 0 // 하나의 블루레이에 들어간 크기 합
        
        for a in arr {
            if sum + a > mid { // 넘친다면
                sum = a // sum 초기화(새로운 것 넣어줌)
                cnt += 1 // cnt += 1
            } else {
                sum += a
            }
        }
        if sum > 0 { cnt += 1 } // 남은거 털기
        
        if cnt > m { // 크기를 너무 작게 잡은 경우 -> cnt가 많아짐
            l = mid + 1
        } else if cnt == m {
            r = mid // 혹시 더 작은 경우가 있나 찾기
        } else { // 크기를 너무 크게 잡은 경우 -> cnt가 적어짐
            r = mid
        }
    }
    
    print(r)
        
}

binarySearch(l: arr.max()!, r: maxV) // 제일 큰 크기보다 작은 조각으로는 쪼갤 수 없음, 다 더한것의 크기 이하여야함.

문제는 간단했는데요, 처음에 mid의 크기보다 작은 값이 들어올때에 대한 처리를 따로 해주다가 시간을 오래 잡아먹었습니다.

사실 생각해보면 arr에서 가장 큰 원소의 크기보다 작은 값으로는 나눌수 없는데 말이죠(이걸 또 백준이라고 생각하고 있던나...) 그래서 처음에는 범위를 0 ~ maxV*n 으로 생각했는데 범위를 다시 조정하게 되어서 arr.max ~ maxV로 조정했습니다.

 

그리고 sum과 cnt를 이용해 카운트를 하는 부분도 위와 같은 이유에서 조금 헷갈렸는데 범위 지정을 해주니 싹~ 해결되었습니다 (대충 개비스콘짤)

 

또 런타임 오류가 50%에서 계속 발생했는데 알고보니 원래는 mid == m일때 answers 배열에 추가를 해준뒤 가장 작은 값을 리턴하도록 구현했었는데 배열에 계속 추가해는 부분이 런타임 에러를 발생한 것 같더라구요..(그걸 빼니까 되네...) 아래와 같이 했다가 알수없는 런타임 오류에 빠져서 고생을 했답니다... append가 그렇게 하기 싫었나... 싶네요 허허...(아래에 첨부) 혹시 Swift로 푸는데 런타임 오류가 발생하신다면 참고해보세요~

if cnt > m { // 크기를 너무 작게 잡은 경우 -> cnt가 많아짐
            l = mid + 1
        } else if cnt == m {
            answers.append(mid)
            r = mid // 혹시 더 작은 경우가 있나 찾기
        } else { // 크기를 너무 크게 잡은 경우 -> cnt가 적어짐
            r = mid
        }
    }
    
    print(answers.min()!)
728x90