본문 바로가기
카테고리 없음

[프로그래머스] 피로도 Javascript

by nh_3521099031483 2024. 4. 11.

 

문제 설명

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 result 입출력 예 설명
k  dungeons  result 
80 [[80,20],[50,40],[30,10]] 3

현재 피로도는 80입니다.

만약, 첫 번째 → 두 번째 → 세 번째 던전 순서로 탐험한다면

  • 현재 피로도는 80이며, 첫 번째 던전을 돌기위해 필요한 "최소 필요 피로도" 또한 80이므로, 첫 번째 던전을 탐험할 수 있습니다. 첫 번째 던전의 "소모 피로도"는 20이므로, 던전을 탐험한 후 남은 피로도는 60입니다.
  • 남은 피로도는 60이며, 두 번째 던전을 돌기위해 필요한 "최소 필요 피로도"는 50이므로, 두 번째 던전을 탐험할 수 있습니다. 두 번째 던전의 "소모 피로도"는 40이므로, 던전을 탐험한 후 남은 피로도는 20입니다.
  • 남은 피로도는 20이며, 세 번째 던전을 돌기위해 필요한 "최소 필요 피로도"는 30입니다. 따라서 세 번째 던전은 탐험할 수 없습니다.

만약, 첫 번째 → 세 번째 → 두 번째 던전 순서로 탐험한다면

  • 현재 피로도는 80이며, 첫 번째 던전을 돌기위해 필요한 "최소 필요 피로도" 또한 80이므로, 첫 번째 던전을 탐험할 수 있습니다. 첫 번째 던전의 "소모 피로도"는 20이므로, 던전을 탐험한 후 남은 피로도는 60입니다.
  • 남은 피로도는 60이며, 세 번째 던전을 돌기위해 필요한 "최소 필요 피로도"는 30이므로, 세 번째 던전을 탐험할 수 있습니다. 세 번째 던전의 "소모 피로도"는 10이므로, 던전을 탐험한 후 남은 피로도는 50입니다.
  • 남은 피로도는 50이며, 두 번째 던전을 돌기위해 필요한 "최소 필요 피로도"는 50이므로, 두 번째 던전을 탐험할 수 있습니다. 두 번째 던전의 "소모 피로도"는 40이므로, 던전을 탐험한 후 남은 피로도는 10입니다.

따라서 이 경우 세 던전을 모두 탐험할 수 있으며, 유저가 탐험할 수 있는 최대 던전 수는 3입니다.

 

생각한 풀이 방법 (1차 시도 -> 실패)

최소 필요 피로도 - 소모 피로도가 가장 큰 순서 부터 처리하면 된다고 생각함
1. 최소 필요 피로도 - 소모 피로도 내림차순으로 dungeons을 정렬
2. dungeons을 탐색 후, 탐험할 수 없으면 해당 값을 반환함

function solution(k, dungeons) {
    let count = 0;
    for (let i = 0; i < dungeons.length; i++) {
        const minValue = Math.min(dungeons[i][0], dungeons[i][1]);
        if (k >= minValue) {
            k -= minValue;
            count++;
        } else {
            break;
        }
    }
    return count;
}

검색한 풀이 방법

  1. DFS를 활용하여 현재 피로도로 각 던전을 방문하여 최대로 탐험할 수 있는 던전 수를 계산
  2. answer의 최대값을 반환함
function solution(k, dungeons) {
    let answer = 0;
    let visited = new Array(dungeons.length).fill(false);


    function DFS(k, count) {

        for(let i=0; i<dungeons.length; i++) {
            if(k >= dungeons[i][0] && !visited[i]) {
                // 방문 체크
                visited[i] = true;
                DFS(k-dungeons[i][1], count + 1);

                // 방문 해제
                // dfs가 다 끝났을 때에 방문 노드를 false해주지 않으면 다른 배열에서 돌 때 true여서 다른 배열이 진행하지 못한다.
                visited[i] = false; 
            }
        }

        answer = Math.max(answer, count);
    }

    DFS(k, 0);

    return answer;
}

 

  1. DFS 함수는 각 던전을 순회하면서 방문 여부와 피로도를 확인.
  2. 만약 현재 피로도가 방문하려는 던전의 최소 필요 피로도보다 크고, 해당 던전이 방문되지 않은 상태라면, 해당 던전을 방문.
  3. 방문한 던전은 방문한 것으로 표시하고, 현재 피로도를 해당 던전을 탐험하는 데 필요한 소모 피로도만큼 감소.
  4. 방문한 던전을 기준으로 다시 DFS를 호출하여 더 깊이 들어감.
  5. DFS의 호출이 종료되면, 현재 탐험한 던전 수를 최대값인 answer와 비교하여 업데이트.

 

dfs를 공부 좀 해야겠다...