문제 설명
XX게임에는 피로도 시스템(0 이상의 정수로 표현합니다)이 있으며, 일정 피로도를 사용해서 던전을 탐험할 수 있습니다. 이때, 각 던전마다 탐험을 시작하기 위해 필요한 "최소 필요 피로도"와 던전 탐험을 마쳤을 때 소모되는 "소모 피로도"가 있습니다. "최소 필요 피로도"는 해당 던전을 탐험하기 위해 가지고 있어야 하는 최소한의 피로도를 나타내며, "소모 피로도"는 던전을 탐험한 후 소모되는 피로도를 나타냅니다. 예를 들어 "최소 필요 피로도"가 80, "소모 피로도"가 20인 던전을 탐험하기 위해서는 유저의 현재 남은 피로도는 80 이상 이어야 하며, 던전을 탐험한 후에는 피로도 20이 소모됩니다.
이 게임에는 하루에 한 번씩 탐험할 수 있는 던전이 여러개 있는데, 한 유저가 오늘 이 던전들을 최대한 많이 탐험하려 합니다. 유저의 현재 피로도 k와 각 던전별 "최소 필요 피로도", "소모 피로도"가 담긴 2차원 배열 dungeons 가 매개변수로 주어질 때, 유저가 탐험할수 있는 최대 던전 수를 return 하도록 solution 함수를 완성해주세요.
제한사항
- k는 1 이상 5,000 이하인 자연수입니다.
- dungeons의 세로(행) 길이(즉, 던전의 개수)는 1 이상 8 이하입니다.
- dungeons의 가로(열) 길이는 2 입니다.
- dungeons의 각 행은 각 던전의 ["최소 필요 피로도", "소모 피로도"] 입니다.
- "최소 필요 피로도"는 항상 "소모 피로도"보다 크거나 같습니다.
- "최소 필요 피로도"와 "소모 피로도"는 1 이상 1,000 이하인 자연수입니다.
- 서로 다른 던전의 ["최소 필요 피로도", "소모 피로도"]가 서로 같을 수 있습니다.
입출력 예시
k | dungeons | return |
80 | [[80,20], [50,40], [30,10]] | 3 |
풀이 코드
DFS, BFS 둘 중 고민하다 입력되는 던전의 크기가 1 ~ 8 이였기 때문에 완전탐색으로 충분이 풀이할 수 있다고 생각했다.
DFS 함수를 재귀호출하면서 방문하지 않았는지, 유저의 피로도가 탐험하고 싶은 던전의 최소 피로도보다 높은지 분기문으로 걸러준다.
해당 분기문을 통과했다면, 던전 방문에 체크하고 (깊이 + 1, 현재 유저 피로도 - 해당 던전 소모 피로도) 를 인자로 다시 재귀호출 !
가능한만큼 최대한 탐색하고 가장 높은 answer 를 정답으로 반환하면 끝나는 문제이다.
DFS 완전탐색 유형에서 자주 방문 체크배열을 만들어서 사용하는데, for 문 동작 시 이미 방문한 노드 (여기서는 던전) 을 걸러 알맞은 i 를
사용할 수 있게 해준다. 예를들어 2번째 던전을 방문하도록 DFS 재귀호출이 되었다면, i 는 0부터 돌지만 이미 첫 번째 던전 (i = 0) 은
방문했기 때문에 아래 분기문에서 걸러지게 되면서 첫 번째 던전의 최소 피로도 Dungeons[0][0] 이 아닌 두 번째 던전의 최소 피로도
Dungeons[1][0] 값과 현재 유저의 피로도를 계산할 수 있게 해준다.
이런 문제는 노드의 끝까지 탐색하는 문제 유형과는 다르게 모든 던전 갯수를 탐색할 수 있을지 아닌지 알 수 없으므로 if-else 구문을
사용해 탈출부분을 만들어주지 않았다. 던전이 3개가 있다면 해당 던전 3개를 모두 탐색할 수 있을지 모르기 때문이다.
완전탐색에서는 재귀호출 구문 아래 방문 체크를 풀어주는 로직을 잊지말자.
class Solution4 {
static int answer;
static int K;
static int node;
static int count;
static int[] checked;
static int[][] Dungeons;
public int solution(int k, int[][] dungeons) {
Dungeons = dungeons;
K = k;
node = dungeons.length;
checked = new int[node];
count = 0;
DFS(0, K);
return answer;
}
private static void DFS(int depth, int k) {
for (int i = 0; i < node; i++) {
if (checked[i] == 0 && k >= Dungeons[i][0]) {
checked[i] = 1;
DFS(depth + 1, k - Dungeons[i][1]);
checked[i] = 0;
}
}
answer = Math.max(answer, depth);
}
}
'알고리즘 정리' 카테고리의 다른 글
자바(Java) 알고리즘 문제풀이 성적이 낮은 순서로 학생 출력하기 [이코테 / 정렬] (0) | 2022.10.09 |
---|---|
자바(Java) 알고리즘 문제풀이 위에서 아래로 [이코테 / 정렬] (0) | 2022.10.09 |
자바(Java) 알고리즘 문제풀이 카펫 [프로그래머스 / 완전탐색] (0) | 2022.09.15 |
자바(Java) 알고리즘 문제풀이 베스트 앨범 [프로그래머스 / Hash] (0) | 2022.08.25 |
자바(Java) 알고리즘 문제풀이 전화번호 목록 [프로그래머스 / Hash] (0) | 2022.08.25 |