해당 문제는 인프런의 강의를 들으며 정리한 Dynamic Programming 냅색 알고리즘 문제이다.
문제 풀이 (JAVA)
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.StringTokenizer;
public class Main {
public static void main(String[] args) throws IOException {
// 동전 교환(냅색 알고리즘)
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
int N = Integer.parseInt(st.nextToken());
int[] arr = new int[N];
st = new StringTokenizer(br.readLine());
for (int i = 0; i < N; i++) {
arr[i] = Integer.parseInt(st.nextToken());
}
st = new StringTokenizer(br.readLine());
int M = Integer.parseInt(st.nextToken());
int[] dy = new int[M + 1];
Arrays.fill(dy, Integer.MAX_VALUE); // 최소를 구할시 Dynamic 배열 최대값으로 초기화
dy[0] = 0; // 첫번째 값은 0 (최소값)
for (int i = 0; i < N; i++) {
for (int j = arr[i]; j <= M; j++) {
dy[j] = Math.min(dy[j], dy[j - arr[i]] + 1); // (이전 최소값 + 1)이 현재 값보다 작다면 교환
}
}
System.out.println(dy[M]);
}
}
정리
1. 해당 동전 문제의 첫번째 포인트는 각 숫자마다 최소 배열을 가지는 dy 배열을 선언하는 것이다.
2. 최소 값을 가져야 하기 때문에 Arrays.fill 함수를 사용하여 dy 배열을 MAX 값으로 초기화해준다.(단, dy[0]은 비교를 위해 0으로 초기화한다.
3. 문제를 풀기 위해서는 (이전 최솟값 +1) 에서 1은 현재 동전을 추가했을때의 경우로, (이전 최솟값 +1)이 현재 값보다 작다면 최솟값을 가지는 경우의 수 이기 때문에 더 작은 값으로 교체해주어야 한다. 이 문제의 핵심 포인트이다.
결론
어느정도 감을 잡았다고 생각을 하였는데, 막상 혼자 풀려니 제대로 된 공식을 생각해내지 못하였다. dp문제를 풀려면 항상 이전 값의 상태를 비교하여 푸는 습관을 들이도록 해야 겠다.
'알고리즘' 카테고리의 다른 글
최대 부분 증가 수열(DP-LIS 알고리즘) (0) | 2023.05.14 |
---|---|
최대점수 구하기(DP-냅색 알고리즘) (0) | 2023.05.14 |
[DFS기초] 경로탐색(DFS) (인프런 알고리즘 7-12) (0) | 2022.07.11 |
[BFS기초] 송아지 찾기(BFS : 상태트리탐색)(인프런 알고리즘 7-8) (0) | 2022.07.11 |
[이분검색] 이분검색 (인프런 알고리즘 6-8) (0) | 2022.07.03 |