알고리즘

[백준] 2293 - 동전 1 (node.js)

내리미 2024. 6. 18. 17:42
문제

 

코드
let fs = require("fs");
// "/dev/stdin"
// "./text.txt"
let input = fs.readFileSync("./text.txt").toString().split("\n");

const [n, k] = input
  .shift()
  .split(" ")
  .filter((v) => v);

let coins = input.map((v) => +v);

let dp = Array(Number(k) + 1).fill(0);
dp[0] = 1;

coins.forEach((v) => {
  for (let j = v; j <= k; j++) {
    dp[j] += dp[j - v];
  }
});

console.log(dp[k]);

 

문제 해결 과정

저번 멘토링 받았던 것을 토대로 우선 문제를 풀기 전 시간 복잡도와 공간 복잡도를 생각해봤다. 

문제 조건이 1 <= n <= 100 이고, 1 <= k <= 10000 이므로 n개의 동전을 사용할 때/사용하지 않을 때를 나눠서 생각해본다면 2^100 이므로 2^10이 1024니까 1024^10정도! 그냥 엄청 크다. 그래서 완전탐색으로는 풀지 못한다고 결정지었다.

그리고 앞서 사용한 동전에 따라 현재 계산할 금액에 영향을 끼치므로 dp를 생각하게 되었다. 

 

문제 플이

 

우선 dp[0]=1을 설정해둔다. 0원을 만들기 위해서 아무런 동전을 사용하지 않는 경우 1가지가 있기 때문이다.

그리고 동전의 금액에 따라 1원부터 k원까지 만들 수 있는 경우의 수를 계산한다. 

즉, dp[k]는 k원을 만들 수 있는 경우의 수이다.

 

예제 입력으로 1원, 2원, 5원 동전이 주어졌을 때 우선 1원짜리 동전으로 k원을 만들 수 있는 경우의 수를 dp에 저장한다. 그리고 1원, 2원자리 동전으로 3원을 만들 수 있는 경우의 수는 아래와 같이 계산해주면 된다.

dp[3](1원,2원짜리 동전으로 표현한 경우의 수) = dp[3](기존 1원짜리 동전만으로 표현한 경우의 수) + dp[1] 

 

그래서 dp[j] += dp[j-v]의 의미는

v(현재 동전 금액)를 1개 사용했을 때 j-v원을 만드는 경우의수 (3원을 만들기 위해 2원짜리 동전 한개를 사용했을 때 1원을 만드는 경우의 수)를 더해준 것이다.

 

이것을 표로 표현해보자.

 

1원짜리 동전만 사용할 때

1 2 3 4 5 6 7 8 9 10
1 1 1 1 1 1 1 1 1 1

 

1원짜리, 2원짜리 동전을 사용할 때

1 2 3 4 5 6 7 8 9 10
1 2 2 3 3 4 4 5 5 6

 

1원짜리, 2원짜리, 5원짜리 동전을 사용할 때

1 2 3 4 5 6 7 8 9 10
1 2 2 3 4 5 6 7 8 10

 

문제점 및 느낀점

 

처음에는 node.js로 풀었는데 메모리초과가 계속 떠서 찾아보니 node.js로는 풀 수 없는 문제였었던 것 같다. 그래서 java로 풀어서 제출했다 ㅜ.ㅜ 그리고 dp 조건을 잡는데 시간이 꽤나 걸렸던 것 같다. 그래서 결국 풀이를 보게 되었는데 풀이도 이해하는데 시간이 좀 걸렸다. dp 문제는 많이 풀어봐야 익숙해질 것 같다 !!

'알고리즘' 카테고리의 다른 글

[SWEA] 8275 햄스터 (java)  (0) 2024.07.12
[백준] 14501 - 퇴사 (node.js)  (0) 2024.07.04
[백준] 1863 - 스카이라인 쉬운거 (node.js)  (2) 2024.06.10