알고리즘

[BOJ] 18427 - 함께 블록 쌓기 (Python, JavaScript)

흙금 2023. 3. 3. 13:10

 

 

아이디어

 

동적 계획법으로 각 블록을 사용하여 탑을 만드는 경우의 수를 구해 나간다.

 

 

풀이 #1 (Python)

 

2624번 동전 바꿔주기 문제 풀이와 유사하다.

 

0으로 채워진 H+1 크기의 리스트 dp를 생성하는데, dp[i]에는 높이 i의 탑을 만드는 경우의 수를 저장한다.

for문에서 리스트 blocks에 블록들의 높이를 입력 받고, temp에 리스트 dp를 복사하여 저장한다.

 

blocks의 블록 하나로 해당 블록의 높이만큼 탑을 쌓는 경우의 수 dp[b]를 1 증가시키고,

해당 블록을 기존 블록들을 함께 사용해 탑을 쌓아 높이 i의 탑을 경우의 수를 temp[i-b]만큼 증가시킨다.

 

높이 H의 탑을 쌓는 경우의 수를 10,007로 나눈 나머지를 출력한다.

 

import sys

input = sys.stdin.readline

def solution():
    N, M, H = map(int, input().split())
    dp = [0]*(H+1)
    for _ in range(N):
        blocks = tuple(map(int, input().split()))
        temp = dp[:]
        for b in blocks:
            dp[b] += 1
            for i in range(b+1, H+1):
                dp[i] += temp[i-b]
    print(dp[-1]%10007)

solution()

 

 

 

풀이 #2 (JavaScript)

 

풀이 #1과 마찬가지 방식으로 동작한다.

 

경우의 수 최댓값이 Number 자료형의 범위를 벗어나므로 계산할 때마다 dp[i]를 10,007로 나눠 범위를 유지한다.

또 if문으로 temp[i-b]의 값이 있을 때만 dp[i]를 계산하도록 한다.

 

const fs = require('fs');
const input = fs.readFileSync('/dev/stdin').toString().split('\n');

const [N, M, H] = input[0].split(' ').map(Number);
let dp = Array(H+1).fill(0);
for (let j=1; j<=N; j++) {
    const blocks = input[j].split(' ').map(Number);
    const temp = [...dp];
    for (let b of blocks) {
        dp[b] += 1;
        for (let i=b+1; i<=H; i++) {
            if (temp[i-b]) {
                dp[i] += temp[i-b];
                dp[i] %= 10007;
            }
        }
    }
}
console.log(dp[H]%10007);