
서로 다른 커피가 N개 있고, 각 커피는 카페인 양이 정해져 있다
몇 개의 커피를 골라 카페인 합을 정확히 K로 만들 때, 마셔야 하는 커피 개수의 최솟값을 구하는 문제다
만약 정확히 K를 만들 수 없다면 -1을 출력한다
각 커피는 한 번만 선택 가능하므로, 전형적인 0/1 배낭(Subset) DP 형태로 바꿀 수 있다
dp[j]를 “카페인 합을 정확히 j로 만들 때 필요한 최소 커피 개수”로 두고, 가능한 경우를 누적 갱신한다
같은 커피를 중복 사용하지 않기 위해 j를 K부터 내려오며(역순) 업데이트하는 것이 핵심이다.
dp[j] = 카페인 합을 정확히 j로 만들 때 필요한 최소 커피 개수 (불가능하면 INF) dp[0] = 0 dp[1..K] = INF 현재 커피의 카페인을 c라고 하면:
dp[j] 유지 j - c여야 하므로 dp[j - c] + 1따라서
dp[j] = min(dp[j], dp[j - c] + 1)
또한 한 커피를 한 번만 쓰기 위해 j는 큰 값부터 내려오며 갱신한다.
dp[K]가 INF 이상이면 만들 수 없는 경우이므로 -1 dp[K] 출력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 K = Integer.parseInt(st.nextToken()); // 목표 카페인 합
int[] caffeineArr = new int[N];
st = new StringTokenizer(br.readLine());
for (int i = 0; i < N; i++) {
caffeineArr[i] = Integer.parseInt(st.nextToken());
}
int INF = 100 * 1000;
int[] dp = new int[K + 1];
Arrays.fill(dp, INF);
dp[0] = 0;
for (int i = 0; i < N; i++) {
int caffein = caffeineArr[i];
for (int j = K; j >= caffein; j--) {
dp[j] = Math.min(dp[j], dp[j - caffein] + 1);
}
}
System.out.println(dp[K] >= INF ? -1 : dp[K]);
}
}