반응형
문제 출처 :
https://www.acmicpc.net/problem/2293
알고리즘 분석 :
문제 해결에 필요한 사항
1. Dynamic Programming
2. 점화식 세우는 방법
해결책이 보이면 아주 간단하고, 잘못 접근하면 조금 까다로운 문제인 것 같다.
나는 두번의 DP 점화식을 거친 후 AC를 받았다.
첫번째 DP 점화식은
1 2 3 4 5 | for (int i = 1; i <= m; i++) for (int j = 0; j < n; j++) if(i - coin[j] >= 0) DP[i] += DP[i - coin[j]]; |
다음과 같이 짰는데, 이 DP는 수행 과정에서 결함이 생긴다.
만약 3원을 만들고 싶다면 1원 + 1원 + 1원 혹은 1원 + 2원으로 하면 3원이 되는데
이 코드는 1원 + 1원 + 1원, 1원 + 2원, 2원 + 1원 총 3개의 답을 도출해주기 때문이다.
따라서 아래와 같이 수정을 함으로써 문제를 해결하였다.
1 2 3 4 | for (int i = 0; i < n; i++) for (int j = 1; j <= m; j++) if (j - coin[i] >= 0) DP[j] += DP[j - coin[i]]; |
이렇게 바꾼 DP 점화식 의미는, 만약 1,2,5원이 있다면
동전 1원으로 만들 수 있는 모든 값을 다 구해주고,(DP[1]~DP[N]까지 모두 1이 되게 된다.)
동전 2원으로 만들 수 있는 모든 값을 다 구해주고,
동전 5원으로 만들 수 있는 모든 값을 다 구해준다.
첫번째 코드는 이번 DP값을 존재하는 COIN들로 더할 수 있으면 DP를 갱신하는 것이고
두번째 코드는 이번 COIN으로 DP값을 갱신 할 수 있다면 DP를 갱신하는 것으로 조금 다르다.
소스 코드 :
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 32 33 34 35 36 37 38 | #include <iostream> #include <cstdio> #include <map> using namespace std; int coin[10002]; int DP[10002]; int main() { int n, m; scanf("%d %d", &n, &m); for (int i = 0; i < n; i++) scanf("%d", &coin[i]); DP[0] = 1; for (int i = 0; i < n; i++) for (int j = 1; j <= m; j++) if (j - coin[i] >= 0) DP[j] += DP[j - coin[i]]; /* for (int i = 1; i <= m; i++) for (int j = 0; j < n; j++) if(i - coin[j] >= 0) DP[i] += DP[i - coin[j]]; */ cout << DP[m]; return 0; } // This source code Copyright belongs to Crocus // If you want to see more? click here >> | Crocus |
반응형
'Applied > 알고리즘 문제풀이' 카테고리의 다른 글
[1015번] 수열 정렬 (2) | 2017.04.25 |
---|---|
[2038번] 골롱 수열 (2) | 2017.04.25 |
[2143번] 두 배열의 합 (2) | 2017.04.25 |
[2170번] 선 긋기 (0) | 2017.04.25 |
[5052번] 전화번호 목록 (0) | 2017.04.25 |