[PCCP 기출문제] 2번 / 퍼즐 게임 챌린지

Updated:

Java

[PCCP 기출문제] 2번 / 퍼즐 게임 챌린지

문제

접근 방법

숙련도를 1에서부터 하나씩 올려서, 퍼즐을 해결하는 최소 숙련도를 구하는 방법으로, 초기 테스트 케이스는 통과할 수 있다.

하지만 위 방법으로는 시간초과가 발생한다. 숙련도의 최대 : 100,000 * 퍼즐의 개수 300,000 = 30,000,000,000 (시간초과) -> O(N * N)

따라서, 1에서 100,000 까지의 숙련도를 최대한 빨리 찾는 방법을 생각해야한다. 그 방법은 이진 탐색(binary Search) 알고리즘을 사용한다.

이진 탐색 알고리즘을 통해 퍼즐을 해결하는 최소 난이도를 빠르게 구한다. -> O(N * log(N))

코드

import java.util.*;

class Solution {
    int[] Diffs;
    int[] Times; 
    long Limit;
    
    public int solution(int[] diffs, int[] times, long limit) {
        Diffs = diffs;
        Times = times; 
        Limit = limit;
        
        // 최대 난이도
        int max = 0;
        for(int i : diffs) {
            max = Math.max(max, i);
        }
        
        int answer = max;
        // 숙련도는 1에서부터 최대난이도 까지 나올 수 있다
        int l = 1,r = max;
        while(l < r) {
            int mid = (l + r) / 2;
            boolean isSolved = cal(mid);
            // 문제가 해결된다면, 현재 난이도가 해결할 수 있는 최소 난이도라 가정
            if(isSolved) {      
                r = mid;
                answer = mid;
            }
            // 문제가 해결되지 않는다면, 남은 절반을 탐색 
            else {    
                l = mid + 1;
            }
        }
        
        return answer;
    }
    
    public boolean cal(int userDiff) {
        int size = Diffs.length;
        int diff = 1;
        int prevTime = 0;
        int curTime = Times[0];
        long totalTime = Times[0];
        
        // 문제 풀기 시작
        for(int i = 1; i < size; i++) {
            diff = Diffs[i];
            prevTime = Times[i - 1];
            curTime = Times[i];

            // 현재 난이도 보다, 어려울 때
            if(diff > userDiff) {
                totalTime += ((diff - userDiff) * (prevTime + curTime) + curTime);
            }
            // 쉬울 때
            else {
                totalTime += curTime;
            }
        }
        
        if(totalTime <= Limit) {
            return true;
        } else {
            return false;
        }
    }
}

코드 해석

각 케이스에서 나올 수 있는 가장 높은 난이도를 구한다 : max 이는 이진 탐색에서 r 으로 사용된다.

또한 최소로 나올 수 있는 숙련도 1 을 l 로 사용한다.

이후 숙련도를 구하기 위한 이진탐색을 시작하고,
문제가 해결 가능한지 계산하는 함수를 별도로 만들어 각 숙련도 케이스마다 문제 해결여부를 확인한다.