본문 바로가기
Study/Algorithm

[2225] 합분해

by ksb0511 2020. 5. 8.

0부터 N까지의 정수 K개를 더해서 그 합이 N이 되는 경우의 수를 구하는 프로그램을 작성하시오.

덧셈의 순서가 바뀐 경우는 다른 경우로 센다(1+2와 2+1은 서로 다른 경우). 또한 한 개의 수를 여러 번 쓸 수도 있다.

 

입력 : 첫째 줄에 두 정수 N(1 ≤ N ≤ 200), K(1 ≤ K ≤ 200)가 주어진다.

출력 : 첫째 줄에 답을 1,000,000,000으로 나눈 나머지를 출력한다.

 


<풀이>

 

 먼저 예시를 들어서 이해를 해보자면, 간단하게 n=2, k=2라고 해보았다.

그럼 0-2 사이의 정수 2개를 더하여 2가 되는 경우의 수를 구하면 된다.

  • 0,2

  • 1,1

  • 2,0

-> 위와 같이 세 가지 경우의 수가 등장한다.

이것을 배열로 표현해보자면 dp[2][2]=3 인 것이다.

 

 

그럼 이제 위의 세 가지 경우의 수를 가지고 점화식을 세워보겠다.

먼저 0, 2의 경우를 보자. 앞의 정수가 0일 경우, 합이 2가 되려면 당연히 2가 와야 한다.

이 2라는 값은 숫자가 한 개이고, 동시에 합이 2다. 그러므로 이 2를 배열로 표현하자면,

이렇게 나타낼 수 있다.

 

한 가지만 예시로 들면 아직 이해하기 어려우므로, 이어서 1,1을 보겠다.

앞의 정수가 이번에는 1이다. 그럼 그 다음 합으로는 당연히 2-1 = 1이 와야 한다.

이 1이라는 값은 숫자가 한 개이고, 동시에 합이 1이다. 그러므로 1을 표현한다면 아래와 같이 표현할 수 있다.

 

 

그럼 이제 마지막으로 2,0의 경우에 0은 자연스럽게 dp[1][0] 이라고 표현할 수 있는 것을 알 수 있다.

 

이 것을 통해 점화식을 세운다면,

dp[i][j] += dp[i-1][j-l] 이라고 세울 수 있다. 좀 더 자세히 설명하자면,

 

 

이 것을 바탕으로 코드를 짜면 아래와 같이 나온다.

import java.util.*;
import java.math.*;

public class Q2225 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub

		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		int k = sc.nextInt();
		long[][] d = new long[k + 1][n + 1];
		d[0][0] = 1;
		for (int i = 1; i <= k; i++) {
			for (int j = 0; j <= n; j++) {
				for (int l = 0; l <= j; l++) {
					d[i][j] += d[i - 1][j - l];
					d[i][j] %= 1000000000;
				}
			}
		}
		System.out.println(d[k][n]);
	}
}

※ 참고로 1000000000을 for문 안에서 나눈 이유는 오버플로우 현상을 방지하기 위해서임.

'Study > Algorithm' 카테고리의 다른 글

[1932] 정수 삼각형  (0) 2020.05.13
[14501] 퇴사  (0) 2020.05.12
[2293] 동전1  (0) 2020.05.07
[9461] 파도반 수열  (0) 2020.05.07
[11726] 2 x n 타일링  (0) 2020.05.06

댓글