본문 바로가기
PS/카카오 기출

[카카오 기출] Swift - 코딩테스트 공부

by kayahn0126 2023. 8. 26.

코딩테스트 공부

  • 2차원 DP
  • 정확성 + 효율성

🍎 지문 해석

  • 알고력과 코딩력을 모든 문제를 풀 수 있도록 키우자!
  • 아래 두가지 방법으로 알고력과 코딩력을 키울 수 있다.
    1. 트레이닝 -> 1시간을 소비해 알고력 또는 코딩력 중 하나를 1 높일 수 있다.
    2. 문제 풀기 -> 알고력, 코딩력이 문제를 풀 수 있는 레벨이 된다면, 문제를 풀어 알고력과 코딩력을 늘릴수 있다.
  • alp는 현재 알고력
  • cop는 현재 코딩력
  • problems는
    • (문제의 풀기위한 알고력,
    • 문제의 풀기위한 코딩력,
    • 문제를 풀었을때 보상 알고력,
    • 문제를 풀었을때 보상 코딩력,
    • 문제를 푸는데 걸리는 시간)
  • 순으로 주어진다.

🍎 문제 접근

  • 문제를 다 푸는데까지 걸리는 최단 시간을 구하는것이 이 문제의 답이다.
  • 매개변수에 주어지는 초기 알고력 or 코딩력이 모든 문제를 풀 수 있는 최대 알고력 or 코딩력을 넘어설 수 있다.
    • 이때는 문제들을 순회하면서 모든 문제를 풀기 위해 필요한 가장 큰 알고력 or 코딩력으로 둔다
    • 이렇게 해야하는 이유는..
        1. 필요 이상의 연산을 하지 않도록 하기 위해서다.
          • 예를들어 모든 문제를 풀기 위해서는 알고력 20, 코딩력 20이 필요하다고 가정해보자
          • 하지만 처음 주어지는 알고력이 25, 코딩력이 10이라면 20까지만 계산해도 될것을 불필요하게 25까지 계산하게 되는것이다.
          • 문제를 풀기위해서는 모든 문제를 풀기위해 필요한 최소의 알고력이다.
          • 즉, 그 이상의 알고력은 필요 없다는 의미다.
        1. 최단 시간을 저장하는 dp배열의 사이즈를 줄일 수 있다.
    • 두가지 이유 모두 퍼포먼스를 드라마틱하게 올려주지 않지만, 필요하지 않은 코드다.

🍎 문제 풀이 및 전체 코드

import Foundation

func solution(_ alp: Int, _ cop: Int, _ problems: [[Int]]) -> Int {
    // alp = 현재 알고리즘 능력
    // cop = 현재 코딩 능력

    // max_alp_req는 최대 알고리즘 능력
    // max_cop_req는 최대 코딩 능력
    // 즉, max에 도달하면 문제를 다 풀 수 있기 때문에 더 이상 진행 시킬 필요없다.
    var max_alp_req = 0
    var max_cop_req = 0

    for problem in problems {
        max_alp_req = max(max_alp_req, problem[0])
        max_cop_req = max(max_cop_req, problem[1])
    }

    //MARK: 초기 주어지는 알고력 or 코딩력이 max 보다 더 클 수 있다.
    var newALP = min(max_alp_req, alp)
    var newCOP = min(max_cop_req, cop)

    //MARK: 범위는 최대 알고력 * 최대 코딩력으로 두었다. 아래서 계산할 때 이 부분을 넘어가지 않도록 막을것.
    var dp = [[Int]](repeating: [Int](repeating: Int.max, count: max_cop_req + 1), count: max_alp_req + 1)
    dp[newALP][newCOP] = 0

    for i in newALP...max_alp_req {
        for j in newCOP...max_cop_req {
            if i + 1 <= max_alp_req { // 알고력 늘려주기
                // 가려는 곳(dp[i+1][j]에 이미 있던 값 vs 이전값 + 1 한것 중 더 작은것으로 갱신 해준다.
                dp[i+1][j] = min(dp[i+1][j], dp[i][j] + 1)
            }
            if j + 1 <= max_cop_req { // 코딩력 늘려주기
                // 가려는 곳(dp[i][j+1])에 이미 있던 값 vs 이전값 + 1 한것 중 더 작은것으로 갱신 해준다.
                dp[i][j+1] = min(dp[i][j+1], dp[i][j] + 1) 
            }
            for problem in problems {
                let alp_req = problem[0]
                let cop_req = problem[1]
                let alp_rwd = problem[2]
                let cop_rwd = problem[3]
                let cost = problem[4]
                //MARK: 현재 i,j가 문제를 풀 수 있는 능력이 된다면(equal or above), 
                if i >= alp_req && j >= cop_req {
                    // 풀었을때 어느 위치로 가는지 찾는다. (이때 i + alp_rwd가 max_alp_req를 넘을 수 있으므로 둘 중 더 작은것을 넣어준다.)
                    let safeALP = min(i + alp_rwd, max_alp_req)
                    let safeCOP = min(j + cop_rwd, max_cop_req)
                    // 해당 위치에 도달 했을때 최소 비용을 구한다.
                    dp[safeALP][safeCOP] = min(dp[safeALP][safeCOP], dp[i][j] + cost)
                }
            }
        }
    }
    return dp[max_alp_req][max_cop_req]
}

🍎 문제를 풀고 생각한 점

  • BFS로 풀려했다가 방문처리가 없다면 무한정 탐색할 것 같아 감 못잡다가 다른분들이 푼것을 조금 더 쉽게 만들었다.
  • 문제를 풀 때 브루트포스를 가장 먼저 생각하는것처럼 최단거리, 최소비용을 구하는 것이라면 DP, 플로이드-와샬(N^3), 다익스트라(ElogV), BFS(가중치가 동일할 때) 순서로 생각하자!
  • 이 문제는 다익스트라로 풀어도 될거 같은데, 시간 복잡도만 계산해보자!
    • N^2log(N^2) -> N^2log(N) -> 20^2log(20) = 400

'PS > 카카오 기출' 카테고리의 다른 글

[카카오 기출] Swift - 셔틀 버스  (1) 2023.08.27
[카카오 기출] Swift - 합승 택시 요금  (0) 2023.08.25