728x90
반응형
SMALL

문제 설명

트럭 여러 대가 강을 가로지르는 일차선 다리를 정해진 순으로 건너려 합니다. 모든 트럭이 다리를 건너려면 최소 몇 초가 걸리는지 알아내야 합니다. 다리에는 트럭이 최대 bridge_length대 올라갈 수 있으며, 다리는 weight 이하까지의 무게를 견딜 수 있습니다. 단, 다리에 완전히 오르지 않은 트럭의 무게는 무시합니다.

예를 들어, 트럭 2대가 올라갈 수 있고 무게를 10kg까지 견디는 다리가 있습니다. 무게가 [7, 4, 5, 6]kg인 트럭이 순서대로 최단 시간 안에 다리를 건너려면 다음과 같이 건너야 합니다.

경과 시간 다리를 지난 트럭 다리를 건너는 트럭 대기 트럭

0 [] [] [7,4,5,6]
1~2 [] [7] [4,5,6]
3 [7] [4] [5,6]
4 [7] [4,5] [6]
5 [7,4] [5] [6]
6~7 [7,4,5] [6] []
8 [7,4,5,6] [] []

따라서, 모든 트럭이 다리를 지나려면 최소 8초가 걸립니다.

solution 함수의 매개변수로 다리에 올라갈 수 있는 트럭 수 bridge_length, 다리가 견딜 수 있는 무게 weight, 트럭 별 무게 truck_weights가 주어집니다. 이때 모든 트럭이 다리를 건너려면 최소 몇 초가 걸리는지 return 하도록 solution 함수를 완성하세요.

제한 조건

  • bridge_length는 1 이상 10,000 이하입니다.
  • weight는 1 이상 10,000 이하입니다.
  • truck_weights의 길이는 1 이상 10,000 이하입니다.
  • 모든 트럭의 무게는 1 이상 weight 이하입니다.

입출력 예

bridge_length weight truck_weights return

2 10 [7,4,5,6] 8
100 100 [10] 101
100 100 [10,10,10,10,10,10,10,10,10,10] 110
package LV2;

import java.util.LinkedList;
import java.util.Queue;

public class H42583 {
    public int solution(int bridge_length, int weight, int[] truck_weights) {
        Queue<Integer> bridge = new LinkedList<>();  // 다리를 표현하기 위한 큐
        int sum = 0;  // 현재 다리 위에 있는 트럭들의 무게 합
        int time = 0;  // 걸리는 시간

        // 각 트럭에 대해
        for (int truck_weight : truck_weights) {
            while (true) {
                if (bridge.isEmpty()) {  // 다리가 비어있다면
                    bridge.offer(truck_weight);  // 트럭을 다리로 보낸다.
                    sum += truck_weight;
                    time++;
                    break;
                } else if (bridge.size() == bridge_length) {  // 다리가 꽉 차 있다면
                    sum -= bridge.poll();  // 다리 맨 앞에 있는 트럭을 내보낸다.
                } else {  // 다리에 여유 공간이 있다면
                    if (sum + truck_weight > weight) {  // 다리 위의 트럭 무게와 대기 중인 트럭 무게의 합이 weight를 초과한다면
                        bridge.offer(0);  // 무게가 0인 트럭을 다리로 보낸다. 이는 대기 상태를 유지하는 것을 의미한다.
                        time++;
                    } else {  // weight를 초과하지 않는다면
                        bridge.offer(truck_weight);  // 트럭을 다리로 보낸다.
                        sum += truck_weight;
                        time++;
                        break;
                    }
                }
            }
        }

        return time + bridge_length;  // 모든 트럭이 다리를 건너는데 걸리는 전체 시간을 반환
    }
}

먼저 다리를 표현하는 큐를 생성한다. 큐의 크기는 다리의 길이를 나타내며, 각 원소는 다리 위의 트럭의 무게를 나타낸다. 트럭이 다리를 건널 때마다 시간을 증가시키고, 트럭이 다리를 빠져나올 때 다리 위의 트럭 무게 합을 갱신한다. 마지막으로, 모든 트럭이 다리를 건너는데 필요한 총 시간을 반환한다.

728x90
반응형
LIST

'알고리즘 > 프로그래머스 JAVA LV.2' 카테고리의 다른 글

뒤에 있는 큰 수 찾기  (0) 2023.06.12
가장 큰 수  (0) 2023.06.07
2 x n 타일링  (0) 2023.06.07
모음사전  (0) 2023.06.07
스킬트리  (0) 2023.06.05
728x90
반응형
SMALL

문제 설명

가로 길이가 2이고 세로의 길이가 1인 직사각형모양의 타일이 있습니다. 이 직사각형 타일을 이용하여 세로의 길이가 2이고 가로의 길이가 n인 바닥을 가득 채우려고 합니다. 타일을 채울 때는 다음과 같이 2가지 방법이 있습니다.

  • 타일을 가로로 배치 하는 경우
  • 타일을 세로로 배치 하는 경우

예를들어서 n이 7인 직사각형은 다음과 같이 채울 수 있습니다.

!https://i.imgur.com/29ANX0f.png

직사각형의 가로의 길이 n이 매개변수로 주어질 때, 이 직사각형을 채우는 방법의 수를 return 하는 solution 함수를 완성해주세요.

제한사항

  • 가로의 길이 n은 60,000이하의 자연수 입니다.
  • 경우의 수가 많아 질 수 있으므로, 경우의 수를 1,000,000,007으로 나눈 나머지를 return해주세요.

입출력 예

n result

4 5

입출력 예 설명

입출력 예 #1

다음과 같이 5가지 방법이 있다.

!https://i.imgur.com/keiKrD3.png

!https://i.imgur.com/O9GdTE0.png

!https://i.imgur.com/IZBmc6M.png

!https://i.imgur.com/29LWVzK.png

!https://i.imgur.com/z64JbNf.png

동적 계획법(Dynamic Programming)을 이용하여 풀 수 있다. 주어진 문제는 피보나치 수열과 매우 비슷하다. 타일을 배치하는 경우의 수는 바로 앞의 타일을 배치한 경우의 수와 그 전의 타일을 배치한 경우의 수를 더한 것과 동일하기 때문이다.

따라서, n이 1일 때와 2일 때의 초기값을 설정한 후, 3부터 n까지의 값을 계산하여 풀 수 있다.

package LV2;

public class H12900 {
    public int solution(int n) {
        int mod = 1_000_000_007;  // 결과값이 매우 커질 수 있으므로, 이를 방지하기 위해 모듈러 연산을 적용할 값이다.

        // n이 1이나 2일 때의 초기값을 위한 동적 계획법 테이블을 설정
        int[] dp = new int[n+1];
        dp[1] = 1;  // 가로 길이가 2, 세로 길이가 1인 타일로 가로 길이가 2, 세로 길이가 1인 바닥을 채우는 방법은 1가지이다.
        dp[2] = 2;  // 가로 길이가 2, 세로 길이가 1인 타일로 가로 길이가 2, 세로 길이가 2인 바닥을 채우는 방법은 2가지이다.

        // 3부터 n까지의 값을 계산한다.
        for (int i = 3; i <= n; i++) {
            // 현재 i 길이의 바닥을 채우는 방법은 
            // i-1 길이의 바닥을 채운 후 세로로 타일을 하나 놓는 방법과 
            // i-2 길이의 바닥을 채운 후 가로로 타일을 두 개 놓는 방법이 있으므로
            // dp[i]는 dp[i-1]과 dp[i-2]의 합이 된다.
            // 그리고 결과값이 너무 커지는 것을 방지하기 위해 모듈러 연산을 적용한다.
            dp[i] = (dp[i-1] + dp[i-2]) % mod;
        }

        return dp[n];  // 최종적으로 계산된 가로 길이가 n인 바닥을 채우는 방법의 수를 반환한다.
    }
}
728x90
반응형
LIST

'알고리즘 > 프로그래머스 JAVA LV.2' 카테고리의 다른 글

가장 큰 수  (0) 2023.06.07
다리를 지나는 트럭  (0) 2023.06.07
모음사전  (0) 2023.06.07
스킬트리  (0) 2023.06.05
주차 요금 계산  (0) 2023.06.05
728x90
반응형
SMALL

문제 설명

사전에 알파벳 모음 'A', 'E', 'I', 'O', 'U'만을 사용하여 만들 수 있는, 길이 5 이하의 모든 단어가 수록되어 있습니다. 사전에서 첫 번째 단어는 "A"이고, 그다음은 "AA"이며, 마지막 단어는 "UUUUU"입니다.

단어 하나 word가 매개변수로 주어질 때, 이 단어가 사전에서 몇 번째 단어인지 return 하도록 solution 함수를 완성해주세요.

제한사항

  • word의 길이는 1 이상 5 이하입니다.
  • word는 알파벳 대문자 'A', 'E', 'I', 'O', 'U'로만 이루어져 있습니다.

입출력 예

word result

"AAAAE" 6
"AAAE" 10
"I" 1563
"EIO" 1189

입출력 예 설명

입출력 예 #1

사전에서 첫 번째 단어는 "A"이고, 그다음은 "AA", "AAA", "AAAA", "AAAAA", "AAAAE", ... 와 같습니다. "AAAAE"는 사전에서 6번째 단어입니다.

입출력 예 #2

"AAAE"는 "A", "AA", "AAA", "AAAA", "AAAAA", "AAAAE", "AAAAI", "AAAAO", "AAAAU"의 다음인 10번째 단어입니다.

입출력 예 #3

"I"는 1563번째 단어입니다.

입출력 예 #4

"EIO"는 1189번째 단어입니다.

package LV2;

public class H84512 {
    public int solution(String word) {
        String vowels = "AEIOU";  // 모음 문자들을 저장
        int answer = 0;  // 결과값을 저장할 변수를 선언
        int permut = 781;  // 첫 번째 자리에 들어갈 수 있는 경우의 수를 저장 (5^4 + 5^3 + 5^2 + 5 + 1)

        for (int i = 0; i < word.length(); i++) {  // 입력 받은 단어를 한 글자씩 순회
            for (int j = 0; j < 5; j++) {  // 모음 문자들을 한 글자씩 순회
                if (vowels.charAt(j) == word.charAt(i)) {  // 만약 모음 문자가 단어의 해당 위치의 문자와 같다면,
                    answer += 1 + j * permut;  // 해당 자리수의 순서를 계산하여 결과값에 더한다.
                }
            }
            permut = (permut - 1) / 5;  // 다음 자리수의 경우의 수를 계산하여 업데이트 한다.
        }

        return answer;  // 최종적으로 계산된 결과값을 반환
    }
}

순열을 이용하여 풀 수 있다. 주어진 알파벳들이 어떻게 배열되는지를 고려하면, 각 알파벳이 몇 번째 위치에 왔을 때 몇 번째 단어가 되는지를 계산할 수 있다.

여기서 중요한 것은, 각 위치에 올 수 있는 경우의 수이다. 예를 들어, 첫 번째 자리에 올 수 있는 경우의 수는 'A', 'E', 'I', 'O', 'U'의 5가지이다. 두 번째 자리에 올 수 있는 경우의 수는 'A', 'E', 'I', 'O', 'U', 'AA', 'AE', 'AI', 'AO', 'AU', ... 등 총 5^2=25가지이다. 마찬가지로 세 번째 자리에 올 수 있는 경우의 수는 5^3=125가지, 네 번째 자리에 올 수 있는 경우의 수는 5^4=625가지, 다섯 번째 자리에 올 수 있는 경우의 수는 5^5=3125가지이다.

따라서, 각 알파벳이 단어의 첫 번째 자리에 올 때는 그 자리에 올 수 있는 경우의 수를 모두 더한 수 만큼 순서가 증가하고, 두 번째 자리에 올 때는 그 자리에 올 수 있는 경우의 수를 모두 더한 수 만큼 순서가 증가한다.

728x90
반응형
LIST

'알고리즘 > 프로그래머스 JAVA LV.2' 카테고리의 다른 글

다리를 지나는 트럭  (0) 2023.06.07
2 x n 타일링  (0) 2023.06.07
스킬트리  (0) 2023.06.05
주차 요금 계산  (0) 2023.06.05
[3차] n진수 게임  (0) 2023.06.05

+ Recent posts