본문 바로가기

Algorithm/Baekjoon Oline Judge - Java

[백준] 2293_동전1 / DP

 

 

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]);
    }
}

 

해결방법

  1. dp 배열을 생성하여 Index 원을 만들 수 있는 경우의 수를 저장한다. 
  2. 동전을 입력받을 때 마다 dp를 업데이트한다. 
    • 입력받은 동전 num 이 j와 같을 때 dp[j]에 1을 더한다. 
    • j가 num보다 값이 클 때 dp[j] = dp[j] + dp[j-num]으로 업데이트한다. 
  3. dp[k]를 출력하여 k원을 만들 수 있는 경우의 수를 리턴한다. 

 

 


 

https://www.acmicpc.net/problem/2293