https://www.acmicpc.net/problem/15989
[필자 사고]
늘 더하기 문제는 숫자들의 순서가 상관이 있었다.
다만 이 문제만의 특별한 점은 순서가 상관이 없다.
즉 필자는 몰랐던 개념을 배웠다.
오름차순 느낌으로 점화식을 설계해야 된다.
dp[i][k] i번째 수는 k이하의 수로 완성한다.
즉 dp[i][k] = dp[i-k][k--] 이런식으로 값을 덮어 씌어야 된다.
이전에 순서가 상관이 있을 때는 값을 += 형태로 더해나가는 동적 프로그래밍이다.
위와 같은 논리를 이해하게 되면 문제를 풀 수 있다.
아래는 자세한 코드 해설입니다.
[코드 해설]
2. 입력 처리 (Input 함수)
Input() 함수는 dp 배열을 초기화하는 역할을 합니다.
- dp 벡터를 크기 10001 × 4로 초기화합니다.
- dp[i][j]는 숫자 i를 만들 때, 1, 2, 3 중 j를 마지막에 사용한 경우의 수를 저장하는 2차원 벡터입니다.
- 0부터 10000까지의 모든 경우를 처리할 수 있도록 dp 배열을 미리 할당합니다.
3. 동적 계획법을 이용한 경우의 수 계산 (Game_Start 함수)
이 함수는 동적 계획법(DP, Dynamic Programming)을 이용하여 1, 2, 3을 사용하여 특정 수를 만드는 방법의 개수를 계산합니다.
- 기본 초기값 설정
- dp[1][1] = 1 → 숫자 1은 1만 사용해서 만들 수 있음
- dp[2][1] = 1, dp[2][2] = 1 → 숫자 2는 1+1 또는 2로 만들 수 있음
- dp[3][1] = 1, dp[3][2] = 1, dp[3][3] = 1 → 숫자 3은 1+1+1, 1+2, 3로 만들 수 있음
- 점화식을 이용한 DP 테이블 채우기
- dp[i][1] = dp[i-1][1]
- i-1까지 1을 사용해서 만든 방법을 그대로 유지
- dp[i][2] = dp[i-2][1] + dp[i-2][2]
- i-2까지 1과 2를 사용해서 만든 방법에 +2를 추가
- dp[i][3] = dp[i-3][1] + dp[i-3][2] + dp[i-3][3]
- i-3까지 1, 2, 3을 사용해서 만든 방법에 +3을 추가
- dp[i][1] = dp[i-1][1]
이렇게 하면 오름차순을 유지하며 숫자를 조합하는 경우의 수를 정확히 구할 수 있습니다.
4. 테스트 케이스 처리 (main 함수)
- T (테스트 케이스 개수)를 입력받습니다.
- Input()을 호출하여 DP 배열을 초기화합니다.
- Game_Start()를 호출하여 DP 테이블을 채웁니다.
- 각 테스트 케이스마다 N을 입력받고, dp[N][1] + dp[N][2] + dp[N][3]을 출력합니다.
- 이는 숫자 N을 만들 수 있는 모든 경우의 수를 합산한 결과입니다.
[소스 코드]
#include <iostream>
#include <vector>
#include <cmath>
#include <algorithm>
using namespace std;
int T;
int N;
vector<vector<long>> dp;
void Input() {
dp.resize(10001);
for (int i = 0; i <= 10000; i++) {
dp[i].resize(4);
}
}
void Game_Start() {
dp[1][1] = 1;
dp[2][1] = 1;
dp[2][2] = 1;
dp[3][1] = 1;
dp[3][2] = 1;
dp[3][3] = 1;
for (int i = 4; i <= 10000; i++) {
dp[i][1] = dp[i - 1][1];
dp[i][2] = dp[i - 2][1] + dp[i - 2][2];
dp[i][3] = dp[i - 3][1] + dp[i - 3][2] + dp[i - 3][3];
}
}
int main(void) {
cin >> T;
Input();
Game_Start();
while (T--) {
cin >> N;
cout << dp[N][1] + dp[N][2] + dp[N][3] << '\n';
}
}
'백준 > 동적프로그래밍' 카테고리의 다른 글
백준 4811 c++ "알약" -PlusUltraCode- (0) | 2025.03.06 |
---|---|
백준 2240 c++ "자두나무" -PlusUltraCode- (0) | 2025.03.06 |
백준 5557 c++ "1학년" -PlusUltraCode- (0) | 2025.03.04 |
백준 9084 c++ "동전" -PlusUltraCode- (0) | 2025.03.04 |
백준 2096 c++ "내려가기" -PlusUltraCode- (0) | 2025.03.02 |