[programmers] Java Lv.2 - 피로도

2025. 2. 17. 13:09·Algorithm Solving/Java

https://school.programmers.co.kr/learn/courses/30/lessons/87946

 

프로그래머스

SW개발자를 위한 평가, 교육, 채용까지 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프

programmers.co.kr

문제 설명
XX게임에는 피로도 시스템(0 이상의 정수로 표현합니다)이 있으며, 일정 피로도를 사용해서 던전을 탐험할 수 있습니다. 이때, 각 던전마다 탐험을 시작하기 위해 필요한 "최소 필요 피로도"와 던전 탐험을 마쳤을 때 소모되는 "소모 피로도"가 있습니다. "최소 필요 피로도"는 해당 던전을 탐험하기 위해 가지고 있어야 하는 최소한의 피로도를 나타내며, "소모 피로도"는 던전을 탐험한 후 소모되는 피로도를 나타냅니다. 예를 들어 "최소 필요 피로도"가 80, "소모 피로도"가 20인 던전을 탐험하기 위해서는 유저의 현재 남은 피로도는 80 이상 이어야 하며, 던전을 탐험한 후에는 피로도 20이 소모됩니다.

이 게임에는 하루에 한 번씩 탐험할 수 있는 던전이 여러개 있는데, 한 유저가 오늘 이 던전들을 최대한 많이 탐험하려 합니다. 유저의 현재 피로도 k와 각 던전별 "최소 필요 피로도", "소모 피로도"가 담긴 2차원 배열 dungeons 가 매개변수로 주어질 때, 유저가 탐험할수 있는 최대 던전 수를 return 하도록 solution 함수를 완성해주세요.

제한사항

  • k는 1 이상 5,000 이하인 자연수입니다.
  • dungeons의 세로(행) 길이(즉, 던전의 개수)는 1 이상 8 이하입니다.
    • dungeons의 가로(열) 길이는 2 입니다.
    • dungeons의 각 행은 각 던전의 ["최소 필요 피로도", "소모 피로도"] 입니다.
    • "최소 필요 피로도"는 항상 "소모 피로도"보다 크거나 같습니다.
    • "최소 필요 피로도"와 "소모 피로도"는 1 이상 1,000 이하인 자연수입니다.
    • 서로 다른 던전의 ["최소 필요 피로도", "소모 피로도"]가 서로 같을 수 있습니다.

 

입출력 예


입출력 예 설명
현재 피로도는 80입니다.

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

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

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

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

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


풀이

던전 방문 순서

던전에 방문하는 모든 순서를 확인해야하므로 DFS와 백트래킹을 활용하여 던전 방문 순서를 생성한다.

import java.util.*;

public class Main {
    static int n;   // 던전 개수
    static boolean[] visited;   // 방문 여부
    static List<int[]> orderList = new ArrayList<>();  // 던전 방문 순서
    static int answer = -1;

    public static void main(String[] args) {
        int k = 80;
        int[][] dungeons = {{80,20},{50,40},{30,10}};

        n = dungeons.length;
        visited = new boolean[n];

        dfs(k, dungeons);
    }

    private static void dfs(int k, int[][] dungeons) {
        // 던전 순서를 모두 뽑으면 종료
        if (orderList.size() == n) {
            for (int[] order : orderList) {
                System.out.print(Arrays.toString(order) + "\t");
            }
            System.out.println();
            
            return;
        }

        // 던전 하나씩 선택
        for (int i = 0; i < n; i++) {
            if (!visited[i]) {
                visited[i] = true;
                orderList.add(dungeons[i]); // 현재 던전을 순서에 추가

                dfs(k, dungeons); // 다음 던전 뽑으러 가기

                // 원상 복구
                orderList.remove(orderList.size() - 1); // 마지막에 추가한 던전 제거
                visited[i] = false; // 방문 여부 되돌리기
            }
        }
    }
}

 

던전 방문 순서의 모든 경우의 수

 

풀이 코드

탐험 순서를 출력(sout)하는 부분을 지우고, 피로도를 계산하게 한다.

import java.util.*;

public class Main {
    static int n;   // 던전 개수
    static boolean[] visited;   // 방문 여부
    static List<int[]> orderList = new ArrayList<>();  // 던전 방문 순서
    static int answer = -1;

    public static void main(String[] args) {
        int k = 80;
        int[][] dungeons = {{80,20},{50,40},{30,10}};

        n = dungeons.length;
        visited = new boolean[n];

        dfs(k, dungeons);

        System.out.println(answer);
    }

    private static void dfs(int k, int[][] dungeons) {
        // 던전 순서를 모두 뽑으면 종료
        if (orderList.size() == n) {
            int fatigue = k;  // 현재 피로도
            int count = 0;     // 탐험한 던전 수

            for (int[] dungeon : orderList) {
                int minRequiredFatigue = dungeon[0];    // 최소 필요 피로도
                int consumeFatigue = dungeon[1];        // 소모 피로도

                if (fatigue >= minRequiredFatigue) {
                    fatigue -= consumeFatigue;
                    count ++;
                } else {
                    break;
                }
            }

            // 최대 던전 수 갱신
            answer = Math.max(count, answer);

            return;
        }

        // 던전 하나씩 선택
        for (int i = 0; i < n; i++) {
            if (!visited[i]) {
                visited[i] = true;
                orderList.add(dungeons[i]); // 현재 던전을 순서에 추가

                dfs(k, dungeons); // 다음 던전 뽑으러 가기

                // 원상 복구
                orderList.remove(orderList.size() - 1); // 마지막에 추가한 던전 제거
                visited[i] = false; // 방문 여부 되돌리기
            }
        }
    }
}

제출

import java.util.*;
class Solution {
    static int n;   // 던전 개수
    static boolean[] visited;   // 방문 여부
    static List<int[]> orderList = new ArrayList<>();  // 던전 방문 순서
    static int answer = -1;
    
    public int solution(int k, int[][] dungeons) {
        n = dungeons.length;
        visited = new boolean[n];
        
        dfs(k, dungeons);
        
        return answer;
    }
    private static void dfs(int k, int[][] dungeons) {
        // 던전 순서를 모두 뽑으면 종료
        if (orderList.size() == n) {
            /*for (int[] order : orderList) {
                System.out.print(Arrays.toString(order) + "\t");
            }
            System.out.println();*/
            int fatigue = k;  // 현재 피로도
            int count = 0;     // 탐험한 던전 수
            for (int[] dungeon : orderList) {
                int minRequiredFatigue = dungeon[0];    // 최소 필요 피로도
                int consumeFatigue = dungeon[1];        // 소모 피로도
                if (fatigue >= minRequiredFatigue) {
                    fatigue -= consumeFatigue;
                    count ++;
                } else {
                    break;
                }
            }
            // 최대 던전 수 갱신
            answer = Math.max(count, answer);
            return;
        }
        // 던전 하나씩 선택
        for (int i = 0; i < n; i++) {
            if (!visited[i]) {
                visited[i] = true;
                orderList.add(dungeons[i]); // 현재 던전을 순서에 추가
                dfs(k, dungeons); // 다음 던전 뽑으러 가기
                // 원상 복구
                orderList.remove(orderList.size() - 1); // 마지막에 추가한 던전 제거
                visited[i] = false; // 방문 여부 되돌리기
            }
        }
    }
}
저작자표시 비영리 변경금지 (새창열림)

'Algorithm Solving > Java' 카테고리의 다른 글

[programmers] Java Lv.2 - 타겟 넘버  (1) 2025.02.18
[programmers] Java Lv.2 - 프로세스  (1) 2025.02.07
[programmers] Java Lv.2 - 기능개발  (0) 2025.01.27
[programmers] Java Lv.2 - 의상  (1) 2025.01.22
[programmers] Java Lv.2 - 할인 행사  (2) 2025.01.21
'Algorithm Solving/Java' 카테고리의 다른 글
  • [programmers] Java Lv.2 - 타겟 넘버
  • [programmers] Java Lv.2 - 프로세스
  • [programmers] Java Lv.2 - 기능개발
  • [programmers] Java Lv.2 - 의상
기만나🐸
기만나🐸
공부한 내용을 기록합시다 🔥🔥🔥
  • 기만나🐸
    기만나의 공부 기록 🤓
    기만나🐸
  • 전체
    오늘
    어제
    • ALL (147)
      • TIL (Today I Learned) (56)
      • Dev Projects (15)
      • Algorithm Solving (67)
        • Java (52)
        • SQL (15)
      • Certifications (8)
        • 정보처리기사 실기 (8)
  • 인기 글

  • 태그

    greedy
    BOJ
    Subquery
    sql
    프로그래머스
    programmers
    join
    javascript
    dp
    시뮬레이션
    HTML
    GROUP BY
    mysql
    자료구조
    DFS
    CSS
    websocket
    백트래킹
    jwt
    Firebase
    jQuery
    그리디
    java
    bootstrap
    BFS
    다이나믹프로그래밍
    완전탐색
    Google Fonts
    백준
    jpa
  • 최근 글

  • 최근 댓글

  • hELLO· Designed By정상우.v4.10.3
기만나🐸
[programmers] Java Lv.2 - 피로도
상단으로

티스토리툴바