재귀로 호출했고 int[10001][101]을 메모이제이션으로 이용.
풀이방식은
DP(won,k) = DP(won - C[k] * 1) + DP(won - C[k] * 2) + ... + DP(won - C[k] * (won/C[k]) )
라고 생각해서 고대로 나타냈다.
won은 돈, C[k]는 k번째 코인의 가격이다.
근데 이대로 풀어서 맞으려면 coinWorth배열, 즉 동전의 가격을 정렬해야 하는데, 왠지 입력을 오름차순으로 친절하게 줄것 같아서 그냥 제출했다.
오답뜨면 그때 오름차순 해보지 머~ 하고 대충 생각함 ㅎ
메모이제이션으로 활용한 배열인 memo[i][j] 는 'j개의 코인으로 i돈을 만들기 위한 가짓 수'이다
처음 시도한 코드.
#include <iostream>
using namespace std;
int memo[10001][101];
int solve(int won, int n) {
if (memo[won][n] > 0) {
return memo[won][n];
}
if (n < 0) {
return 0;
}
if (won < 0) {
return 0;
}
if (n == 0) {
if (won % coinWorth[n] == 0) return memo[won][n] = 1;
}
int result = 0;
int limit = (int)(won / coinWorth[n]);
for (int i = 0; i <= limit; i++) {
result += solve(won - coinWorth[n] * i, n - 1);
}
return memo[won][n] = result;
}
int main() {
int coinN, resultWon;
cin >> coinN >> resultWon;
for (int i = 0; i < coinN; i++) {
cin >> coinWorth[i];
}
int result = solve(resultWon, coinN - 1);
cout << result << endl;
}
근데 오답이 아니라 메모리초과가 뜨더라
멍청한 나는 재귀때문인줄 알고 반복문으로 고쳤다
근데 멍청해서 반복문으로 고치는 것도 넘넘 오래 걸려따
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int coinWorth[101];
int memo[10001][101];
int main() {
int coinN, resultWon;
cin >> coinN >> resultWon;
for (int i = 0; i < coinN; i++) {
cin >> coinWorth[i];
}
int i = 0;
while (true) {
if ((coinWorth[0] * i > resultWon)) break;
memo[(coinWorth[0] * i)][0] = 1;
i++;
}
for (int j = 1; j < coinN; j++) {
for (int i = 0; i <= resultWon; i++) {
for (int k = 0; k <= i / coinWorth[j]; k++) {
memo[i][j] += memo[i - (int)(coinWorth[j] * k)][j - 1];
}
}
}
int result_final = memo[resultWon][coinN - 1];
cout << result_final << endl;
}
코드 길이가 줄긴 했는데
당연히 메모리 초과 ㅎ
메모리 제한이 4MB인걸 그제서야 찾았다
아 백만짜리 int를 써서 그런건가.. 싶어서 곰곰히 생각해봤다.. 이걸 줄일수 있나
멍청해서 곰곰히가 아니라 고되게 생각한 끝에
'아! memo[i][j]를 구할때는 memo[i][j-1]만 있으면 돼는구나!'
싶어서
아래와 같이 구현
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int coinWorth[101];
int memo[10001];
int prevMemo[10001];
int main() {
int coinN, resultWon;
cin >> coinN >> resultWon;
for (int i = 0; i < coinN; i++) {
cin >> coinWorth[i];
}
int i = 0;
while (true) {
if ((coinWorth[0] * i > resultWon)) break;
memo[(coinWorth[0] * i)] = 1;
i++;
}
for (int j = 1; j < coinN; j++) {
for (int x = 0; x <= resultWon; x++) {
prevMemo[x] = memo[x];
memo[x] = 0;
}
for (int i = 0; i <= resultWon; i++) {
for (int k = 0; k <= i / coinWorth[j]; k++) {
memo[i] += prevMemo[i - (int)(coinWorth[j] * k)];
}
}
}
int result_final = memo[resultWon];
cout << result_final << endl;
}
맞췄다!
근데 맞추고 나서 안건데
http://hsp1116.tistory.com/23
이걸 보니까....
허참.... 내가 더 멍청해보인다
힝...
'코딩 > 알고리즘' 카테고리의 다른 글
백준 2156 포도주 시식 (0) | 2017.05.22 |
---|---|
백준 1005 ACM Craft (1) | 2017.05.21 |
백준 2579 계단 오르기 (0) | 2017.05.21 |
백준 1463 1로 만들기 (0) | 2017.05.21 |
백준 10844 쉬운 계단 수 (0) | 2017.05.21 |