Gold
문제
n가지 종류의 동전이 있다. 각각의 동전이 나타내는 가치는 다르다.
이 동전을 적당히 사용해서, 그 가치의 합이 k원이 되도록 하고 싶다. 그 경우의 수를 구하시오.
각각의 동전은 몇 개라도 사용할 수 있다.
사용한 동전의 구성이 같은데, 순서만 다른 것은 같은 경우이다.
입력
첫째 줄에 n, k가 주어진다. (1 ≤ n ≤ 100, 1 ≤ k ≤ 10,000)
다음 n개의 줄에는 각각의 동전의 가치가 주어진다.
동전의 가치는 100,000보다 작거나 같은 자연수이다.
출력
첫째 줄에 경우의 수를 출력한다. 경우의 수는 2^31보다 작다.
풀이-1 DFS
import java.util.*;
class Main {
static int[] arr;
static int count = 0;
static int N, k;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
N = sc.nextInt();
k = sc.nextInt();
arr = new int[N];
sc.nextLine();
for(int i=0; i<N; i++){
arr[i] = sc.nextInt();
}
Arrays.sort(arr);
dfs(0, 0);
System.out.println(count);
}
public static void dfs(int depth, int sum){
if(sum > k) return;
if(sum==k){
count +=1;
return;
}
for(int i=depth; i<N; i++){
dfs(i, sum + arr[i]);
}
}
}
처음에는 깊이탐색을 이용해 모든 경우의 수를 구하려 했다.
그러나 입려 된 수가 클수록 모든 조합의 수를 탐색하려다 보니 시간초과가 발생하게 되었다.
이 문제를 해결하기 위해선 동적계획법 DP를 사용해야 했다.
풀이 2 - DP
import java.util.*;
class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int N = sc.nextInt();
int k = sc.nextInt();
int[] dp = new int[k+1];
sc.nextLine();
for(int i=0; i<N; i++){
int num = sc.nextInt();
for(int j=0; j<= k; j++){
if(j > num) dp[j] = dp[j] + dp[j-num];
else if(j-num == 0) dp[j]+=1;
}
}
System.out.println(dp[k]);
}
}
해결방법
- dp 배열을 생성하여 Index 원을 만들 수 있는 경우의 수를 저장한다.
- 동전을 입력받을 때 마다 dp를 업데이트한다.
- 입력받은 동전 num 이 j와 같을 때 dp[j]에 1을 더한다.
- j가 num보다 값이 클 때 dp[j] = dp[j] + dp[j-num]으로 업데이트한다.
- dp[k]를 출력하여 k원을 만들 수 있는 경우의 수를 리턴한다.
https://www.acmicpc.net/problem/2293
'Algorithm > Baekjoon Oline Judge - Java' 카테고리의 다른 글
[백준] 1026_보물 / visited (0) | 2024.08.25 |
---|---|
[백준] 10844_쉬운계단수 / DP (0) | 2024.08.25 |
[백준] 2247_별찍기10 / 재귀 (1) | 2024.08.18 |
[백준] 1806_부분합 / 투포인터 (0) | 2024.08.11 |
[백준] 11660_구간 합 구하기5 / DP, 누적합 (0) | 2024.08.11 |