문제출처 : https://www.acmicpc.net/problem/2225


1. 문제요약

- 0 부터 N까지의 정수 K개를 더해서 그 합이 N이 되는 경우의 수

- 1 + 2와 2 + 1은 다른 경우

- 숫자는 중복해서 사용 가능

- 1 <= N <= 200

- 1 <= K <= 200


2. 접근방법

- 숫자 N은 N-0 + 0

               N-1 + 1

               N-2 + 2

               N-3 + 3

               ...

               N-N + N

  으로 만들 수 있음

- d[n][k] : K번째 합이 N인 경우의 수라 하면


- d[n][k] = d[n-0][k-1] + d[n-1][k-1] + d[n-2][k-1] + ... + d[n-n][k-1]


3. 시간복잡도

- O(KN^2) = 8,000,000


4. 회고

- 합산 결과가 int를 넘는가?

- 재귀 리턴값이 옳바른가?


- mod 연산 할때

- <소스 2> 처럼 했었는데 틀리고 <소스 1>은 맞음

- <소스 2> : d[sum][cnt] = (A mod div + B mod div + ... N mod div) mod div 가 들어가고

  <소스 1> : d[sum][cnt] = (A mod div + B mod div + ... N mod div) mod div 가 들어가는데?


- 어라 근데 return d[sum][cnt] %= div 인데.. 연산자 우선순위 때문인가? 괄호 안쳐서 그런가?

  해봐야겠다


- <소스 1>은 맞고 <소스 2>가 틀린 이유는 '메모이제이션' 때문....

- <소스 1>의 d 배열에는 나머지 값이 들어가 있어서 line 6에서 정상적으로 나머지값이 반환됨.

- <소스 2>의 d 배열에는 나머지 값이 들어가 있지 않아서 line 6에서 나머지 연산 전의 값이 반환됨.

  <소스 2>의 line 6를 return d[sum][cnt] % div로 바꿔주면 정답


- <소스 2>의 line 11을 return d[sum][cnt] %= div로 바꿔주면 제일 빨리 수행됨

  나머지 연산이 덧셈 때 마다들어가지 않기 때문에


- 예를 들어 div = 5일 때,

  1 1 1   1 1 1   1 1 1

    3         3        3

              9 // <소스 1>은 9div5 = 4가 저장되고 / <소스 2>는 9가 저장됨

              ...

              12 // <소스 1>과 <소스 2> 모두 합은 4 + 4 + 4 이지만

                     <소스 1>은 12div5 = 2가 <소스 2>는 12가 저장됨

                      메모이제이션할때 저장된 값을 리턴하면

                     <소스 1>은 2를 <소스 2> 는 12를 리턴하므로 틀린 값이 나옴

                     그래서 <소스 2>의 line 6를 return d[sum][cnt] % div로 바꿔주면 정답이 됨.

long long dp(int sum, int cnt){
	if (cnt == 1)
		return 1;

	if (d[sum][cnt])
		return d[sum][cnt];

	for (int i = 0; i <= sum; i++){
		d[sum][cnt] += dp(sum - i, cnt - 1);
		d[sum][cnt] %= 1000000000;
	}

	return d[sum][cnt];
}

<소스 1>


long long dp(int sum, int cnt){
	if (cnt == 1)
		return 1;

	if (d[sum][cnt])
		return d[sum][cnt];

	for (int i = 0; i <= sum; i++)
		d[sum][cnt] += dp(sum - i, cnt - 1);

	return d[sum][cnt] % 1000000000;
}

<소스 2>



소스코드 : Top-Down


소스코드 : Bottom-Up



[출처 : BOJ, 문제에 대한 모든 권리는 BOJ(acmicpc.net, startlink)에 있음]

'먹고살려면 > boj' 카테고리의 다른 글

BOJ 11052 붕어빵 판매하기  (0) 2018.01.25
BOJ 2011 암호코드  (0) 2018.01.25
BOJ 9461 파도반 수열  (0) 2018.01.24
BOJ 1966 제곱수의 합  (0) 2018.01.23
BOJ 2579 계단 오르기  (0) 2018.01.22

+ Recent posts