일명 냅색 알고리즘은 크게 두 가지 문제로 분류 될 수 있다.
import java.io.*;
import java.util.*;
public class Main2 {
static int N, K;
static int[] W;
static int[] V;
static int[][] dp;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
N = Integer.parseInt(st.nextToken());
K = Integer.parseInt(st.nextToken());
W = new int [N + 1];
V = new int [N + 1];
dp = new int[N+1][K+1];
for(int i = 1; i <= N; i++){
st = new StringTokenizer(br.readLine());
W[i] = Integer.parseInt(st.nextToken());
V[i] = Integer.parseInt(st.nextToken());
}
for(int i = 1; i <= N; i++){
for(int j = 1; j <= K; j++){
if(W[i] > j){
dp[i][j] = dp[i-1][j];
}else{
dp[i][j] = Math.max(dp[i-1][j] , dp[i-1][j - W[i]] + V[i]);
}
}
}
System.out.print(dp[N][K]);
}
}
👉 0번 인덱스를 사용하기 위해:
예를 들어, dp[0][...]는 어떤 물건도 고려하지 않았을 때의 상태를 의미.
물건의 개수가 N개일 때, 인덱스는 1부터 N까지 사용하므로, 0번 인덱스를 포함해서 N+1개의 공간이 필요!
dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - W[i]] + V[i]);
for (int j = 1; j <= K; j++) { // 무게
for (int i = 1; i <= N; i++) { // item
if (W[i] > j) {
dp[i][j] = dp[i - 1][j];
}
else {
dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - W[i]] + V[i]);
}
}
}
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= K; j++) {
if (W[i] > j) {
dp[i][j] = dp[i - 1][j];
}
else {
dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - W[i]] + V[i]);
}
}
}
무게 기준 반복 (첫 번째 코드)의 경우, 무게가 커질수록 DP 테이블을 채우는 데 더 많은 시간이 걸릴 수 있다!!
예시:
아이템 정보:
아이템 | 무게 (W) | 가치 (V) |
---|---|---|
1 | 10 | 60 |
2 | 20 | 100 |
3 | 30 | 120 |
4 | 40 | 140 |
5 | 50 | 160 |
첫 번째 코드 (무게 기준 반복):
for (int j = 1; j <= K; j++) { // 무게
for (int i = 1; i <= N; i++) { // item
// ...
}
}
j
를 1부터 100까지 순차적으로 증가시키면서 각 무게에 대해 아이템을 하나씩 고려합니다.dp[i-1][j-W[i]] + V[i]
를 계산해야 하기 때문에 시간이 오래 걸립니다. j - W[i]
가 음수가 되는 경우도 발생합니다. 이 경우 dp[i-1][j-W[i]]
는 의미가 없기 때문에 불필요한 계산을 수행하게 됩니다.두 번째 코드 (아이템 기준 반복):
for (int i = 1; i <= N; i++) { // item
for (int j = 1; j <= K; j++) { // 무게
// ...
}
}
i
를 하나씩 고려하면서 각 아이템에 대해 가능한 모든 무게를 검사합니다.결론:
추가 설명:
따라서, 무게가 큰 경우에는 아이템 기준 반복 (두 번째 코드)가 더 효율적인 선택입니다.