-
[백준/BOJ] 2293번 동전 1 (C++)알고리즘 문제풀이/백준 2020. 12. 21. 19:58
2293번: 동전 1
첫째 줄에 n, k가 주어진다. (1 ≤ n ≤ 100, 1 ≤ k ≤ 10,000) 다음 n개의 줄에는 각각의 동전의 가치가 주어진다. 동전의 가치는 100,000보다 작거나 같은 자연수이다.
www.acmicpc.net
DP 유형의 문제입니다.
점화식을 도출해내기 위해서 동전의 종류가 1원, 2원, 5원이 있고 숫자 10을 만드는 경우의 수를 구한다고 했을 때 밑의 예시를 살펴보겠습니다.
1 2 3 4 5 6 7 8 9 10 1 1 1 1 1 1 1 1 1 1 1번부터 10번까지 dp 테이블을 만들고, 동전 1원으로 만들 수있는 경우를 살펴보면 전부 1개입니다. 그렇다면 다음으로 1원과 2원을 이용한 경우는 어떻게 되는지 살펴보겠습니다.
1 2 3 4 5 6 7 8 9 10 1 1 1 1 1 1 1 1 1 1 1 2 2 3 3 4 4 5 5 6 dp 테이블의 숫자 2부터 수가 변한 것을 확인할 수 있습니다. 숫자 2를 만들 수 있는 경우는 1+1, 2 총 2가지 입니다. 더 살펴보겠습니다. 숫자 3을 만드는 경우는 1+1+1, 1+2 총 2가지 입니다. 이를 통해 한가지 규칙을 찾아낼 수 있는데, 새로 갱신되는 dp[n]의 값은 이전 dp[n] 값에서 dp[n - 현재 동전의 종류 크기] 를 더한 값이라는 점입니다.
1 2 3 4 5 6 7 8 9 10 1 1 1 1 1 1 1 1 1 1 1 2 2 3 3 4 4 5 5 6 1 2 2 3 4 5 6 7 8 10 1원, 2원, 5원을 이용하는 경우입니다. 이번에는 숫자 5부터 수가 변한 것을 확인할 수 있습니다. 그리고 역시나 같은 규칙을 가지고 있습니다. 따라서 위의 방법과 동일하게 모든 동전의 종류에 대해서 dp 테이블의 값을 갱신하면 됩니다. 이러한 과정을 거치므로 점화식은 다음과 같이 정의할 수 있습니다.
dp[n] = dp[n] + dp[n - v[i])
#include <iostream> #include <vector> using namespace std; int dp[10001]; int main(void) { ios_base::sync_with_stdio(false); cin.tie(0); int n, k; cin>>n>>k; vector<int> v(n + 1); for(int i = 1; i <= n; i++) { cin>>v[i]; } // 초기값 설정 dp[0] = 1; // 동전의 종류마다 k번까지 최대 경우의 수가 갱신된다. for(int i = 1; i <= n; i++) { // 동전의 종류와 같은 수부터 갱신된다. (그 이전은 그대로 유지) for(int j = v[i]; j <= k; j++) { dp[j] += dp[j - v[i]]; } } cout<<dp[k]; }
'알고리즘 문제풀이 > 백준' 카테고리의 다른 글
[백준/BOJ] 15671번 오델로 (C++) (0) 2020.12.22 [백준/BOJ] 4539번 반올림 (C++) (0) 2020.12.22 [백준/BOJ] 18353번 병사 배치하기 (C++) (0) 2020.12.21 [백준/BOJ] 11053번 가장 긴 증가하는 부분 수열 (C++) (0) 2020.12.21 [백준/BOJ] 1912번 연속합 (C++) (0) 2020.12.20