정수 4를 1, 2, 3의 합으로 나타내는 방법은 총 4가지가 있다. 합을 나타낼 때는 수를 1개 이상 사용해야 한다. 합을 이루고 있는 수의 순서만 다른 것은 같은 것으로 친다.
- 1+1+1+1
- 2+1+1 (1+1+2, 1+2+1)
- 2+2
- 1+3 (3+1)
정수 n이 주어졌을 때, n을 1, 2, 3의 합으로 나타내는 방법의 수를 구하는 프로그램을 작성하시오.
입력
첫째 줄에 테스트 케이스의 개수 T가 주어진다. 각 테스트 케이스는 한 줄로 이루어져 있고, 정수 n이 주어진다. n은 양수이며 10,000보다 작거나 같다.
출력
각 테스트 케이스마다, n을 1, 2, 3의 합으로 나타내는 방법의 수를 출력한다.
예제 입력 1
3
4
7
10
예제 출력 1
4
8
14
1. 문제 분석
기존 1, 2, 3 더하기 문제와의 차이
https://www.acmicpc.net/problem/9095
보통의 1, 2, 3 더하기 문제(예: 백준 9095번)는 순서를 따집니다.
- 예: 와 을 다른 경우로 셈.
- 이때의 점화식:
이 문제(15989)의 핵심
하지만 이 문제는 순서가 달라도 구성이 같으면 같은 경우로 생각합니다.
- 예: 와 은 같은 경우 (중복 제거 필요)
2. 동전 교환 알고리즘과 유사!!
순서 중복을 없애는 가장 확실한 방법은 수를 오름차순으로만 사용하도록 정하는 것입니다.
1을 모두 사용한 뒤 2를 쓰고, 그 뒤에 3을 쓰는 방식으로만 합을 구성하면, 같은 순서 뒤집힘이 발생하지 않습니다.
-> 동전 교환 문제
흐름
Step 1: 1만 사용하여 만드는 경우 모든 수는 1의 합으로 나타낼 수 있습니다. ()
- 초기화: 모든 (혹은 에서 시작하여 갱신)
Step 2: 2를 추가하여 만드는 경우 이미 1로만 구성된 경우의 수에, 이제 2를 섞어서 만들 수 있는 경우를 더합니다.
- 점화식:
- 를 만드는 모든 방법 뒤에 2를 하나 붙인다.
Step 3: 3을 추가하여 만드는 경우 1과 2로 구성된 경우의 수에, 마지막으로 3을 섞는 경우를 더합니다.
- 점화식:
- 을 만드는 모든 방법 뒤에 3을 하나 붙인다.
for 문의 순서가 중요. 동전을 바깥쪽 루프에 두고, 금액을 안쪽 루프에 두어야 중복 없는 조합이 계산됨
3. 코드
테스트 케이스가 여러 개지만, 의 최댓값이 10,000으로 작으므로 DP 테이블을 미리 한 번만 채워두고 결과를 조회하는 것이 효율적
import sys
input = sys.stdin.readline
# 1. 입력 받기
T = int(input())
nums = [int(input()) for _ in range(T)]
# 2. DP 테이블 초기화
# 문제 조건에 따라 n은 최대 10,000
max_n = 10000
dp = [0] * (max_n + 1)
# 초기값: 0을 만드는 방법은 아무것도 선택하지 않는 1가지
dp[0] = 1
# 3. DP
# 숫자를 하나씩 고정하고 dp 테이블 전체를 갱신한다.
# 이렇게 하면 (1, 2) 조합 다음 (1, 3)이 올 수 있어도,
# (2, 1) 처럼 순서가 바뀌는 경우는 발생하지 않는다.
for num in [1, 2, 3]: # 사용할 수 있는 숫자
for i in range(num, max_n + 1):
dp[i] += dp[i - num]
# 4. 결과 출력
for n in nums:
print(dp[n])
4. 정리
이 문제의 교훈은 DP에서 루프의 순서가 의미를 바꾼다는 것입니다.
- 순서가 중요할 때 -순열: target을 바깥 루프, coins를 안쪽 루프로.
- 순서가 중요하지 않을 때 -조합: coins를 바깥 루프, target을 안쪽 루프로.
이 문제는 순서가 중요하지 않으므로 2번 방식을 사용하여 해결했습니다.
'백준' 카테고리의 다른 글
| [백준] 7490번 - 0만들기 (0) | 2026.02.04 |
|---|---|
| [백준] 2531번 - 회전초밥 (0) | 2026.02.04 |
| [백준] 1205번 - 등수 구하기 (0) | 2026.02.02 |
| [백준] 9665번 - 돌게임 (0) | 2026.02.02 |
| [백준] 9665번 - 지름길 문제 (0) | 2026.02.02 |