티스토리 뷰

728x90
반응형

목차

     

    문제

     

    n가지 종류의 동전이 있다. 

    각각의 동전이 나타내는 가치는 다르다. 

    이 동전을 적당히 사용해서, 그 가치의 합이 k원이 되도록 하고 싶다. 

    그 경우의 수를 구하시오. 

    각각의 동전은 몇 개라도 사용할 수 있다.

    사용한 동전의 구성이 같은데, 순서만 다른 것은 같은 경우이다.

     

    입력

     

    첫째 줄에 n, k가 주어진다. (1 ≤ n ≤ 100, 1 ≤ k ≤ 10,000) 

    다음 n개의 줄에는 각각의 동전의 가치가 주어진다. 

    동전의 가치는 100,000보다 작거나 같은 자연수이다.

     

    출력

     

    첫째 줄에 경우의 수를 출력한다. 

    경우의 수는 $2^{31}$보다 작다.

     

    풀이

     

    무한히 많이 주어진 유한한 가치의 동전들로 특정 값을 만들 수 있는 경우의 수를 구하는 문제이다.

     

    그러니까 예를 들면 동전이 두 종류(가치는 1, 5)가 있고 10이라는 값을 만들어 내려면

     

    (1, 1, 1, 1, 1, 1, 1, 1, 1, 1), (1, 1, 1, 1, 1, 5), (5, 5)의 세 가지 경우의 수가 생기며,

     

    같은 종류의 동전이지만 순서만 바뀐 것은 하나로 처리한다.

     

    문제를 푸는 방식은 아래와 같다.

     

    1. 입력받은 동전의 가치를 기반으로 반복문을 돌면서 각 가치를 만들 수 있는 경우의 수를 구한다.
    2. dp 배열에 현재 동전으로 만들 수 있는 각 가치의 경우를 누적합으로 계산한다.

    이를 기반으로 코드를 간단하게 살펴보면,

     

    1. 동전의 개수(n)와 목표 금액(k)을 입력받아 각각 coins와 dp 배열의 크기를 초기화하고 coins는 주어진 값으로 채운다.
    2. dp[0]은 1로 설정한다. 이는 만들어야 하는 가치가 0인 경우 아무 동전도 선택하지 않는 경우의 수가 하나 있기 때문이다.
    3. 각 동전에 대해 반복문을 돌면서 해당 동전의 가치부터 목표금액(k)까지 dp 값을 갱신한다.
      이때 dp[j]에 dp[j - coins[i]]를 누적하며 더하는 이유는 j라는 가치를 만드는 방법에
      현재 동전(coins[i])을 사용하는 경우를 추가하는 것이다.
    4. 모든 동전에 대해 순회한 후 dp[k]를 출력한다.

    Additional Explain

     

    3번의 경우에 대해 조금 이해가 어려울 수 있는데, 조금 더 예를 들면 아래와 같은 로직을 사용하는 것이다.

     

    먼저, 주어진 동전이 1, 2원 두 개라고 가정하고, 4원을 만드는 과정을 생각해 보자.

     

    이때, 초기화된 dp 배열은 [1, 0, 0, 0, 0]와 같이 생겼다.

     

    1. 1원 동전 사용

    반복문을 시작해 1원부터 사용해 보자. 현재 동전의 가치인 1원부터 목푯값인 4원까지 모든 경우에 대해

     

    dp[j] += dp[j - 1]을 수행하면 된다.

     

    • j = 1 → dp[1] += dp[0] → dp[1] = 1 (1원을 만드는 법은 1원 동전 한 개)
    • j = 2 → dp[2] += dp[1] → dp[2] = 1 (2원을 만드는 법은 1원 동전 한 개)
    • j = 3 → dp[3] += dp[2] → dp[3] = 1 (3원을 만드는 법은 1원 동전 한 개)
    • j = 4 → dp[4] += dp[3] → dp[4] = 1 (4원을 만드는 법은 1원 동전 한 개)

    순회가 끝나면 dp는 [1, 1, 1, 1, 1]로 갱신된다.

     

    1. 2원 동전 사용

    계속해서 다음 동전인 2원 동전을 사용해 보자. 현재 동전의 가치인 2원부터 목푯값인 4원까지 계산을 수행한다.

     

    • j = 2 → dp[2] += dp[0] → dp[2] = 2 (2원을 만드는 법은 1원 동전 두 개, 2원 동전 한 개)
    • j = 3 → dp[3] += dp[1] → dp[3] = 2 (3원을 만드는 법은 1원 동전 세 개, 1원 동전 한 개 + 2원 동전 한 개)
    • j = 4 → dp[4] += dp[2] → dp[4] = 3 (4원을 만드는 법은 1원 동전 네 개, 1원 동전 두 개 + 2원 동전 한 개, 2원 동전 두 개)

     

    계산이 끝나면 최종적으로 dp는 [1, 1, 2, 2, 3]이 된다.

     

    문제에서 주어진 조건은 dp[4]이므로, 3이 원하는 답이 되는 것이다.

     

    Java

     

    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.util.StringTokenizer;
    
    public class Prob2293 {
    
    	public static void main(String[] args) throws IOException {
    
    		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    
    		StringTokenizer st = new StringTokenizer(br.readLine());
    		int n = Integer.parseInt(st.nextToken());
    		int k = Integer.parseInt(st.nextToken());
    		int[] coins = new int[n];
    		int[] dp = new int[k + 1];
    
    		for (int i = 0; i < n; i++) {
    			coins[i] = Integer.parseInt(br.readLine());
    		}
    
    		dp[0] = 1;
    
    		for (int i = 0; i < n; i++) {
    			for (int j = coins[i]; j <= k; j++) {
    				dp[j] += dp[j - coins[i]];
    			}
    		}
    
    		System.out.println(dp[k]);
    	}
    }

     

    Python

     

    import sys
    
    n, m = map(int, sys.stdin.readline().rstrip().split(" "))
    memories = [0] + list(map(int, sys.stdin.readline().rstrip().split(" ")))
    costs = [0] + list(map(int, sys.stdin.readline().rstrip().split(" ")))
    
    sum_cost = sum(costs)
    dp = [0] + [float("-inf") for _ in range(sum_cost)]
    
    for i in range(1, n + 1):
        for j in range(sum_cost, costs[i] - 1, -1):
            dp[j] = max(dp[j], dp[j - costs[i]] + memories[i])
    
    result = 0
    
    for i in range(sum_cost + 1):
        if dp[i] >= m:
            result = i
            break
    
    print(result)

     

    Performance

     

    반응형
    댓글
    공지사항
    최근에 올라온 글
    최근에 달린 댓글
    Total
    Today
    Yesterday
    링크
    «   2024/05   »
    1 2 3 4
    5 6 7 8 9 10 11
    12 13 14 15 16 17 18
    19 20 21 22 23 24 25
    26 27 28 29 30 31
    글 보관함