백준의 합분해(2225) 문제이다.
( 문제 바로가기 )
[ 문제풀이 ]
1) 이 문제는 0 ~ N까지의 숫자 중에서 K개를 더해서 그 합이 N이 되는 경우의 수를 구하는 문제이다.
그렇다면 작은 숫자부터 어떻게 풀어나가야 할지 알아보자.
먼저 본인은 이 경우의 수를 저장하기 위해서 DP[][] 2차원 배열을 사용하였다.
DP[a][b] = c 의 의미는 "a개 더해서 그 합이 b가 되는 경우의 수는 c개 입니다." 이다.
즉, 우리가 구해야 할 결과값은 DP[K][N]의 값이다.
그렇다면 DP[1][N] 의 값은 얼마일까 ?? N이 무슨 값이든 상관없이 DP[1][N]의 결과는 1이다.
어떤 수를 한 개만 더해서 N이 나오는 경우의 수는 N값 그 자신 하나밖에 없기 때문이다.
위의 식은 초기설정 값이라고 볼 수 있다.
또한, K가 0일 경우 DP[K][x] = 0 이라고 볼 수 있다. 어떤 수를 0개를 더해서 합이 x가 되는 경우는 없기 때문에 0이다.
그렇다면 , 2개를 더해서 2가 나오는 경우의 수에 대해서 알아보자.
K = 2 , N = 2 인 경우이다.
(0 + 2) , (1 + 1), (2 + 0) 이렇게 총 3개의 경우가 있을 것이다.
조금 더 식을 구체적으로 써보자면
0 + 2 = (한개를 더해서 0이 나오는 경우) + (한개를 더해서 2가 나오는 경우)
1 + 1 = (한개를 더해서 1이 나오는 경우) + (한개를 더해서 1이 나오는 경우)
2 + 0 = (한개를 더해서 2가 나오는 경우) + (한개를 더해서 0이 나오는 경우)
위의 과정처럼 0부터 N까지 진행을 한다고 생각해보면 점화식은
DP[K][N] = DP[K-1][0] + DP[K-1][1] + ... + DP[K-1][N]이 된다.
또한 연산결과를 Moduler값으로 나눠줘야 한다는 점에 주의하고, DP배열의 값 자체도 long long 으로 바꿔줘야지만
맞았습니다를 받을 수 있다.
[ 소스코드 ]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | #include<iostream> typedef long long ll; #define endl "\n" #define MAX 201 #define Moduler 1000000000 using namespace std; int N, K; ll DP[MAX][MAX]; void Input() { cin >> N >> K; } void Solution() { for (int i = 0; i <= N; i++) { DP[1][i] = 1; } for (int k = 2; k <= K; k++) { for (int n = 0; n <= N; n++) { for (int i = 0; i <= n; i++) { DP[k][n] = DP[k][n] + DP[k - 1][i]; } DP[k][n] = DP[k][n] % Moduler; } } cout << DP[K][N] << endl; } void Solve() { Input(); Solution(); } int main(void) { ios::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL); //freopen("Input.txt", "r", stdin); Solve(); return 0; } | cs |
'[ BOJ Code ] > # BOJ -' 카테고리의 다른 글
[ 백준 1063 ] 킹 (C++) (2) | 2019.02.02 |
---|---|
[ 백준 2239 ] 스도쿠 (C++) (0) | 2019.02.02 |
[ 백준 15654 , 15655 ] N과M(5) , N과M(6) (C++) (0) | 2019.02.01 |
[ 백준 11559 ] Puyo Puyo (C++) (0) | 2019.02.01 |
[ 백준 6087 ] 레이저 통신 (C++) (3) | 2019.02.01 |