18427번: 함께 블록 쌓기
첫째 줄에 자연수 N, M, H가 공백을 기준으로 구분되어 주어진다. (1 ≤ N ≤ 50, 1 ≤ M ≤ 10, 1 ≤ H ≤ 1,000) 둘째 줄부터 N개의 줄에 걸쳐서 각 학생이 가진 블록들의 높이가 공백을 기준으로 구
www.acmicpc.net
문제
1번부터 N번까지의 학생들은 각각 블록들을 가지고 있다. 학생마다 최대 M개의 블록을 가지고 있을 수 있으며, 한 명의 학생이 가지고 있는 모든 블록들의 높이는 서로 다르다. 이 때 1번부터 N번까지의 학생들이 가진 블록을 차례대로 사용하여 바닥에서부터 쌓아올려 하나의 탑을 만들고자 한다.
단, 어떤 학생의 블록은 사용하지 않아도 되며 한 학생당 최대 1개의 블록만을 사용할 수 있다.
1번부터 N번까지의 학생들이 가지고 있는 블록들에 대한 정보가 주어졌을 때, 높이가 정확히 H인 탑을 만들 수 있는 경우의 수를 계산하는 프로그램을 작성하시오.
예를 들어 N=3, M=3, H=5일 때, 각 학생마다 가지고 있는 블록들의 높이가 다음과 같다고 가정하자.
- 1번 학생: 2, 3, 5
- 2번 학생: 3, 5
- 3번 학생: 1, 2, 3
이 때, 탑의 높이가 정확히 5가 되도록 블록을 쌓는 경우로는 다음의 6가지가 존재한다. (블록을 사용하지 않는 경우는 X로 표시하였다.)
입력
첫째 줄에 자연수 N, M, H가 공백을 기준으로 구분되어 주어진다. (1 ≤ N ≤ 50, 1 ≤ M ≤ 10, 1 ≤ H ≤ 1,000) 둘째 줄부터 N개의 줄에 걸쳐서 각 학생이 가진 블록들의 높이가 공백을 기준으로 구분되어 주어진다.
단, 모든 블록의 높이는 1,000 이하의 자연수이며 한 명의 학생이 가지고 있는 모든 블록들의 높이는 서로 다르게 주어진다.
출력
첫째 줄에 높이가 H인 탑을 만드는 경우의 수를 10,007로 나눈 나머지를 출력한다.
코드
from collections import defaultdict
n, m, h = map(int, input().split())
dp = defaultdict(int)
dp[0] += 1
for _ in range(n):
possible = []
for num in list(map(int, input().split())):
for i in dp.keys():
possible.append((i+num, dp[i]))
for a, b in possible:
dp[a] += b
print(dp[h]%10007)
DP배열을 defaultdict로 만들어서
따로 possible 배열에 담았다가 DP배열을 업데이트해주는 이유는 한 학생당 최대 1개의 블록만 사용할 수 있다는 조건 때문이다. 그리고 딕셔너리의 키가 반복문을 도는 도중에 변경될 수 있기 때문에 에러가 발생할 수 있다.
그렇지만 이렇게 하면 비효율적인 것 같아서 다른 사람들은 어떻게 풀었나 찾아봤더니 2차원 배열로 많이 푸는 것 같아서 다시 풀어보았다.
n, m, h = map(int, input().split())
dp = [[0]*(h+1) for _ in range(n+1)]
dp[0][0] = 1
for i in range(1, n+1):
# i번째 학생의 블럭을 사용하지 않는 경우
for j in range(h+1):
dp[i][j] = dp[i-1][j]
# i번째 학생의 블럭을 사용하는 경우
for block in list(map(int, input().split())):
for j in range(block, h+1):
dp[i][j] += dp[i-1][j-block]
print(dp[-1][h]%10007)
행은 학생의 번호, 열은 높이를 나타내는 DP 배열을 만들어서 풀이하였다.
i번째 학생의 블럭을 사용하는 경우와 사용하지 않는 경우 2가지로 나누어서 풀이하였다.
- 사용 X
이전 학생이 같은 높이를 쌓을 때 가능한 경우의 수를 그대로 갖고 온다. - 사용 O
이전 학생이 (구하는 높이-사용하려는 블럭 높이)를 쌓을 때 가능한 경우의 수를 갖고 와서 더해준다.
1번째 풀이보다 2번째 풀이인 2차원 배열로 풀이하니 훨씬 효율적이었다.
'문제풀이 > DP' 카테고리의 다른 글
[Python/파이썬] 백준 1082번 방 번호 (0) | 2023.07.14 |
---|---|
[Python/파이썬] 백준 2616번 소형기관차 (0) | 2023.07.09 |
[Python/파이썬] 백준 2294번 동전 2 (0) | 2023.05.30 |
[Python/파이썬] 백준 2293번 동전 1 (0) | 2023.05.29 |
[Python/파이썬] 백준 1106번 호텔 (0) | 2023.05.28 |