백준 BOJ 2225번 : 합분해
Solved.ac 난이도 : Gold V
알고리즘 분류 : DP, 조합론
0~N까지의 수 K개를 조합하여 N을 만들 수 있는 경우의 수를 구하는 문제입니다.
이 때 중요한 것은, 수의 순서가 바뀌면 다른 조합으로 고려하며 조합에 0이 들어갈 수 있다는 것입니다.
즉 수 2개로 1을 조합하는 경우의 수는 (0, 1)과 (1, 0)으로 총 2가지입니다.
DP로 풀어야 함은 쉽게 파악이 가능한데, 수의 중복 허용과 순서 고려 때문에 경우의 수를 구하기가 쉽지 않습니다.
따라서 상황을 다음과 같이 전환시켜 생각하면 좋습니다.
0 이상의 정수 K개를 조합하여 N을 만들기 → N개의 공을 K-1개의 막대로 경계지어 K개의 묶음으로 나누기
예시를 들면 다음과 같습니다.
위는 4개의 공을 4개의 막대로 나누어 5개의 묶음으로 나눈 하나의 경우입니다.
즉, N = 4, K = 5일 때 그 중 하나의 경우입니다.
막대 사이에 공이 없다면 0으로 생각할 수 있습니다.
위의 그림의 경우에는 4 = 1 + 2 + 0 + 1 + 0으로 분할한 것입니다.
우리는 0 이상의 정수로의 분할을 위와 같은 공과 막대로의 배열로 일대일 대응시켜 생각할 수 있습니다.
이것은 N개의 공과 K-1개의 막대의 배치이므로, N+K-1 C K-1로 생각할 수 있습니다.
따라서 그냥 Combination만 dp로 계산해서 출력해주면 쉽게 답을 얻을 수 있습니다.
#include<bits/stdc++.h>
#define MAX 401
#define MOD 1000000000
using namespace std;
int combination(int N, int K) {
if(N < K) return 0;
int dp[MAX][MAX] = {1};
for(int i=1; i<=N; i++)
for(int j=0; j<=i; j++)
dp[i][j] = (dp[i-1][j-1] + dp[i-1][j]) % MOD;
return dp[N][K];
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL), cout.tie(NULL);
int N, K; cin >> N >> K;
cout << combination(N+K-1, K-1);
}
Combination을 계산할 때는 n C k = n-1 C k-1 + n-1 C k라는 점화식을 이용하여 쉽게 계산할 수 있습니다.
물론 이 때 0 C 0 = 1로 정의해주고 연쇄적으로 계산시켜주어야 합니다.
모듈로 계산도 빠뜨리면 안됩니다.
'알고리즘 > 백준(BOJ) 문제풀이' 카테고리의 다른 글
BOJ 1717 집합의 표현 / BOJ 15988 1, 2, 3 더하기 3 / BOJ 1699 제곱수의 합 (0) | 2022.04.17 |
---|---|
BOJ 6588 골드바흐의 추측 / BOJ 1916 최소비용 구하기 / BOJ 1406 에디터 (0) | 2022.04.17 |
BOJ 2146 다리 만들기 (DFS, BFS) (0) | 2022.04.14 |
BOJ 11057 오르막 수 / BOJ 10026 적록색약 / BOJ 14503 로봇 청소기 (DP, DFS, 구현) (1) | 2022.04.11 |
BOJ 6603 로또 / BOJ 1759 암호 만들기 / BOJ 2468 안전 영역 (백트래킹, DFS) (0) | 2022.04.11 |