[BOJ 2225][Gold 5] 합분해
제한
시간제한 | 메모리 제한 | 제출 | 정답 | 맞은 사람 | 정답 비율 |
---|---|---|---|---|---|
2초 | 128MB | 26597 | 11473 | 8271 | 41.550% |
문제
0부터 N까지의 정수 K개를 더해서 그 합이 N이 되는 경우의 수를 구하는 프로그램을 작성하시오.
덧셈의 순서가 바뀐 경우는 다른 경우로 센다(1+2와 2+1은 서로 다른 경우). 또한 한 개의 수를 여러 번 쓸 수도 있다.
입력
첫째 줄에 두 정수 N(1 ≤ N ≤ 200), K(1 ≤ K ≤ 200)가 주어진다.
출력
첫째 줄에 답을 1,000,000,000으로 나눈 나머지를 출력한다.
틀린 풀이
처음에 일단 단순 재귀호출로 풀어봤습니다. 그러나 시간복잡도가 지수함수로 매우 크기 때문에 시간초과가 떴습니다.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
public class Main {
static int N;
static int K;
static int Cnt;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
N = Integer.parseInt(st.nextToken());
K = Integer.parseInt(st.nextToken());
dfs(0,0);
System.out.println(Cnt);
}
private static void dfs(int d,int sum) {
if(d==K){
if(sum==N) Cnt=(Cnt+1)%1000000000;
return;
}
for(int i = 0 ; i <= N ; i++){
if(sum+i<=N) dfs(d+1,sum+i);
}
}
}
풀이
다른 방법을 찾아보기위해서 규칙을 찾아보도록 case를 쭉 적어봤다. 하나씩 나열해보면
(N=0, K=1) ->1 ,(N=0, K=2) ->1 ,(N=0, K=3) ->1, …
(N=1, K=1) =>1 ,(N=1, K=2) ->2 ,(N=1, K=3) ->3, …
(N=2, K=1) =>1 ,(N=2, K=2) ->3 ,(N=2, K=3) ->6, …
(N=3, K=1) =>1 ,(N=2, K=2) ->4 ,(N=2, K=3) ->10, …
쭉 나열해본 결과
f(N,K)= f(N-1,K)+ f(N,K-1) (N=0 일 경우 1)
과 같은 점화식이 도출된다. 그래서 n X k 이차원배열을 만들어서 0번째 행의 1번째 열부터 K까지 1로 초기화한 후에, 1번째 1열부터 N번째 K 까지 점화식을 적용(%1000000000 연산과 같이)한다. 수행이 끝난 뒤에 배열의 N행 K열의 값을 출력한다.
소스코드
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
public class Main {
static int N;
static int K;
static int[][] dp;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
N = Integer.parseInt(st.nextToken());
K = Integer.parseInt(st.nextToken());
dp = new int[N+1][K+1];
for(int i = 1 ; i <= K ; i++) dp[0][i] = 1;
for(int i = 1 ; i <= N ; i++){
for(int j = 1; j <= K ; j++){
dp[i][j]=(dp[i-1][j]+dp[i][j-1])%1000000000;
}
}
System.out.println(dp[N][K]);
}
}
알고리즘 분류
- 수학
- 다이나믹 프로그래밍