Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- BOJ 1926
- BOJ 2167
- BOJ 1074
- javascript
- BOJ 1697
- Coercion
- BOJ 4485
- DP
- priority_queue
- BOJ 4948
- spring security
- BOJ 1912
- BOJ 5568
- 분할과 정복
- BOJ 2213
- 다익스트라
- BOJ 2234
- BOJ 2407
- 플로이드 와샬
- BOJ 2012
- serverless
- springboot
- MySQL
- BOJ 6593
- BOJ 5791
- BOJ 11726
- Lambda
- 조합 알고리즘
- AWS
- BOJ 2146
Archives
- Today
- Total
고인물을 지양하는 블로그
BOJ 2293 동전 1 본문
https://www.acmicpc.net/problem/2293
2293번: 동전 1
첫째 줄에 n, k가 주어진다. (1 ≤ n ≤ 100, 1 ≤ k ≤ 10,000) 다음 n개의 줄에는 각각의 동전의 가치가 주어진다. 동전의 가치는 100,000보다 작거나 같은 자연수이다.
www.acmicpc.net
를 다음과 같이 정의하자.
원 까지 이용해 j원을 만드는 경우의 수
따라서 원을 이용하는(할 수 있는) 경우, 이용하지 않는 경우 두 가지 경우로 나눌 수 있다.
각각의 경우는

이다.
따라서 점화식은 다음과 같다.

코드 1
#include <cstdio>
#include <cstring>
#include <algorithm>
int N,K;
bool bound(int i, int j) {return i>=0&&i<N&&j>=0&&j<=K;}
int max(int a,int b) {return a>b?a:b;}
int main() {
scanf("%d%d",&N,&K);
int c[N],d[K+1];
memset(d,0,K+1);
for(int i=0;i<N;++i)
scanf("%d",&c[i]);
std::sort(c,c+N); // 오름차순으로 동전 정렬
for(int i=0;i<N;++i)
d[i][0] = 1;
for(int i=1;i<=K;++i)
d[0][i] = 1;
// 초기조건
for(int i=1;i<N;++i) {
for(int j=1;j<=K;++j) {
d[i][j] = (bound(i,j-c[i])?d[i][j-c[i]]:0) + (bound(i-1,j)?d[i-1][j]:0);
// c[i]원을 사용 하는 경우, c[i]원을 사용 안하는 경우
}
}
printf("%d",d[N-1][K]);
// c[N-1]원까지 이용해 K원을 만드는 가짓수 출력
}
2차원 배열을 이용하면 점화식을 거의 그대로 옮긴 수준의 코드로 작성할 수 있다. 다만 문제에서는 메모리가 4MB로 제한돼 있으므로 메모리 초과가 발생한다. (발생했다)
코드 2
#include <cstdio>
#include <cstring>
#include <algorithm>
int N,K;
int main() {
scanf("%d%d",&N,&K);
int c[N],d[K+1];
memset(d,0,sizeof(d));
for(int i=0;i<N;++i)
scanf("%d",&c[i]);
d[0] = 1;
for (int i=0;i<N;i++)
for (int j=1;j<=K;j++)
if (j>=c[i])
d[j]+=d[j-c[i]];
// c[i]원을 사용하지 않고 j원을 만드는 경우 + c[i]원을 사용하고 j원을 만드는 경우 합
printf("%d",d[K]);
}