이번 문제는 잘못된 풀이 또한 함께 제시해 보려고 한다.
잘못된 아이디어
- 이차원 배열로 풀 수 있을 것 같다 DP [101][10'001]
이차원 배열은 불가능한 듯하다
$$101 \times 10'001 \times 4 = 4'040'404byte = 4.040404mb$$
최대 4mb인데 4mb를 넘어가 버린다
점화식
$$dp [j][i] = dp [j][i-coin [j]]\; + \;dp [j][i]\; + \;\sum_{k = 1}^{j-1} dp [j-k][i-coin [j]]$$
답은 맞게 나온다 사실 맞는 지도 모른다..., 하지만 메모리 초과가 뜬다.... 그래도 열심히 풀었으니 코드는 올려본다
#include <bits/stdc++.h>
using namespace std;
void init(){
ios_base::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
}
int n, k;
int coin[101];
int dp[101][10'001];
int main(){
init();
//입력
cin >> n >> k;
for(int i = 1; i <= n; ++i)
cin >> coin[i];
//연산
for(int i = 1; i <= k; ++i){
for(int j = 1; j <= n; ++j){
if(i-coin[j] == 0)dp[j][i]=1;
else if(i-coin[j] > 0){
dp[j][i] = dp[j][i-coin[j]];
for(int k = 1; k <= j-1; ++k)
dp[j][i] += dp[j-k][i-coin[j]];
}
}
}
int cnt = 0;
for(int i = 1; i <=n; ++i)
cnt += dp[i][k];
cout << cnt;
return 0;
}
좋은 풀이
답을 보고 난 후의 풀이다.
coin = {1, 2, 5} 동전을 사용해 10원을 만들려 한다 동전의 순서는 신경 쓰지 않는다. (즉, 중복 불가능)
동전 coin [ i ]를 사용해 j의 가치를 만들 수 있는 경우의 수
- 1원을 사용해 1을 만들 수 있는 경우의 수 : 1개
- 1원을 사용해 2를 만들 수 있는 경우의 수 : 1개
- ...
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
- 2원을 사용해 1을 만들 수 있는 경우의 수 : 0개
- 2원을 사용해 2를 만들 수 있는 경우의 수 : 1개
- 2원을 사용해 3을 만들 수 있는 경우의 수 : 2개
- ...
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
1 | 1 | 1 + dp[0] | 1+dp[1] | 1+dp[2] | 1+dp[3] | 1+dp[4] | 1+dp[5] | 1+dp[6] | 1+dp[7] | 1+dp[8] |
- 5원을 사용해 1을 만들 수 있는 경우의 수 : 0개
- ....
- 5원을 사용해 5를 만들 수 있는 경우의 수 : 1개
- 5원을 사용해 6을 만들 수 있는 경우의 수 : 1개
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
1 | 1 | 2 | 2 | 3 | 3 + dp[0] | 4+dp[1] | 4+dp[2] | 5+dp[3] | 5+dp[4] | 6+dp[5] |
5를 사용하여 7을 만드는 경우의 수 => 7-5 = 2
= 2를 만드는 경우의 수 + 현재 dp [7]
결과
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
1 | 1 | 2 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 10 |
나의 생각으로는 애초에 처음부터 중복을 배재해 왔기 때문에 중복이 없는 것이라 생각한다.
점화식
$$dp [j] += dp [j-coin [i]]$$
CODE
using namespace std;
void init(){
ios_base::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
}
int n, k;
int coin[101];
int dp[10'001];
int main(){
init();
cin >> n >> k;
for(int i = 1; i <= n; ++i)
cin >> coin[i];
dp[0] = 1;
for(int i = 1; i <= n; ++i){
for(int j = coin[i]; j <= k; ++j){
dp[j] += dp[j-coin[i]];
}
}
cout << dp[k];
return 0;
}
'💻 Computer > 🐘 Algorithm' 카테고리의 다른 글
[2294] 동전 2 - C++ (0) | 2023.06.22 |
---|---|
[1107] 리모컨 - C++ (0) | 2023.06.22 |
[1018] 체스판 다시 칠하기 - C++ (0) | 2023.06.19 |
[11502] 카드 구매하기 - c++ (0) | 2023.06.19 |
[2302] 극장좌석 - c++ (0) | 2023.06.17 |