알고리즘
[프로그래머스] 퍼즐 게임 챌린지 - JAVA 풀이
sppl24
2024. 10. 28. 23:17
반응형
퍼즐 게임 챌린지
문제 설명
당신은 순서대로 n
개의 퍼즐을 제한 시간 내에 풀어야 하는 퍼즐 게임을 하고 있습니다. 각 퍼즐은 난이도와 소요 시간이 정해져 있습니다. 당신의 숙련도에 따라 퍼즐을 풀 때 틀리는 횟수가 바뀌게 됩니다. 현재 퍼즐의 난이도를 diff
, 현재 퍼즐의 소요 시간을 time_cur
, 이전 퍼즐의 소요 시간을 time_prev
, 당신의 숙련도를 level
이라 하면, 게임은 다음과 같이 진행됩니다.
diff
≤level
이면 퍼즐을 틀리지 않고time_cur
만큼의 시간을 사용하여 해결합니다.diff
>level
이면, 퍼즐을 총diff
-level
번 틀립니다. 퍼즐을 틀릴 때마다,time_cur
만큼의 시간을 사용하며, 추가로time_prev
만큼의 시간을 사용해 이전 퍼즐을 다시 풀고 와야 합니다. 이전 퍼즐을 다시 풀 때는 이전 퍼즐의 난이도에 상관없이 틀리지 않습니다.diff
-level
번 틀린 이후에 다시 퍼즐을 풀면time_cur
만큼의 시간을 사용하여 퍼즐을 해결합니다.
예를 들어 diff = 3, time_cur = 2, time_prev = 4인 경우, level에 따라 퍼즐을 푸는데 걸리는 시간은 다음과 같습니다.
level
= 1이면, 퍼즐을 3 - 1 = 2번 틀립니다. 한 번 틀릴 때마다 2 + 4 = 6의 시간을 사용하고, 다시 퍼즐을 푸는 데 2의 시간을 사용하므로 총 6 × 2 + 2 = 14의 시간을 사용하게 됩니다.level
= 2이면, 퍼즐을 3 - 2 = 1번 틀리므로, 6 + 2 = 8의 시간을 사용하게 됩니다.level
≥ 3이면 퍼즐을 틀리지 않으며, 2의 시간을 사용하게 됩니다.
퍼즐 게임에는 전체 제한 시간 limit
가 정해져 있습니다. 제한 시간 내에 퍼즐을 모두 해결하기 위한 숙련도의 최솟값을 구하려고 합니다. 난이도, 소요 시간은 모두 양의 정수며, 숙련도도 양의 정수여야 합니다.
퍼즐의 난이도를 순서대로 담은 1차원 정수 배열 diffs, 퍼즐의 소요 시간을 순서대로 담은 1차원 정수 배열 times, 전체 제한 시간 limit이 매개변수로 주어집니다. 제한 시간 내에 퍼즐을 모두 해결하기 위한 숙련도의 최솟값을 정수로 return 하도록 solution 함수를 완성해 주세요.
제한 사항
- 1 ≤
diffs
의 길이 =times
의 길이 =n
≤ 300,000diffs[i]
는 i번째 퍼즐의 난이도,times[i]
는i
번째 퍼즐의 소요 시간입니다.diffs[0]
= 1- 1 ≤
diffs[i]
≤ 100,000 - 1 ≤
times[i]
≤ 10,000
- 1 ≤
limit
≤ 10^15- 제한 시간 내에 퍼즐을 모두 해결할 수 있는 경우만 입력으로 주어집니다.
입출력 예
아이디어
- 레벨을 0부터 하나씩 올리면 시간초과에 걸린다
- 최고 난이도가 10만이라는 것을 캐치 하고 이분탐색 O(logN) 으로 구현할 수 있다는 것만 캐치하면 나머지 조건은 어렵지 않다
- limit 최댓값도 10^15면 충분
JAVA 풀이
import java.util.*;
class Solution {
public int solution(int[] diffs, int[] times, long limit) {
int answer = 0;
int min = 1;
int max = 100000; // 최고 난이도
while (min <= max) {
int level = (min + max) / 2;
long total = getTotal(diffs, times, level);
if (total <= limit) {
answer = level;
max = level - 1;
} else {
min = level + 1;
}
}
return answer;
}
public long getTotal(int[] diffs, int[] times, int level) {
long timeSum = 0;
for (int i = 0; i < diffs.length; i++) {
if (diffs[i] <= level) {
timeSum += times[i];
} else {
// 레벨이 미치지 못할 경우 추가되는 시간 계산
long diff = (long) (diffs[i] - level);
// 틀린 경우 (diff > level): (이전꺼 + 지금꺼 시간) * (난이도 - 레벨) + 지금꺼 시간
if (i > 0) {
timeSum += diff * (times[i] + times[i - 1]) + times[i];
} else {
timeSum += (diff * times[i]) + times[i];
}
}
}
return timeSum;
}
}
반응형