Notice
Recent Posts
Recent Comments
Link
공부 기록장
[DP] 0/1 Knapsack 본문
0/1 knapsack, 배낭채우기 문제는 DP에서 유명한 문제 중 하나이다.
1) N개의 물건에 각각 무게 정보와 가치 정보가 주어지고
2) W의 무게까지 담을 수 있는 가방이 있을 때,
3) 가방의 가치를 가장 높게 만들어 줄 물건들을 담아야 한다.
보통은 도둑이 물건을 훔쳐갈 때, 들고갈 수 있는 무게는 제한적이니 그런 것들을 이용해서 알고리즘 문제가 나오더라.
하지만 오늘은 특정 문제를 포스팅 하는게 아니라, 알고리즘 자체를 올려보려고 한다.
이 알고리즘의 로직은
1) 첫 물건부터 끝 물건까지, 가방의 무게를 1부터 W까지 모두 고려해서
2) 물건의 무게가 현재 가방의 무게보다 작거나, 같으면 넣어본다.
2-1) 이번 아이템을 넣지 않았을 때와, 넣었을 때를 비교해서 더 큰 값을 저장해주는 방식이다.
3) 만약 물건의 무게가 현재 가방의 무게보다 크다면 이전 상태를 가져간다.
저 로직을 실행하기 위해 N*W 사이즈의 배열이 하나 더 필요하다.
for문이 다 돌고 나면, (N,W) 자리의 값이 우리가 원하는 값이 된다.
package ex_0325;
import java.util.Arrays;
import java.util.Scanner;
public class Knapsack {
//0-1 Knapsack
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc = new Scanner(System.in);
int N = sc.nextInt(); //물건의 개수
int W = sc.nextInt(); //가방의 무게
int[] weights = new int[N+1]; //물건의 무게정보
int[] profits = new int[N+1]; //물건의 가치정보
int[][] D = new int[N+1][W+1]; //해당 물건까지 고려하여 해당 무게를 만들 떄 까지 최대 가치
for(int i=1; i<N+1; i++) { //물건이 0개일 때도 고려하기 위해 0은 0으로.
weights[i] = sc.nextInt();
profits[i] = sc.nextInt();
}
for(int i=1; i<N+1; i++) { //첫 물건부터 끝 물건까지.
for(int w=1; w<W+1; w++) {//가방의 무게 1부터 W까지 모두 고려.
if(weights[i] <= w) {
//물건의 무게가 현재 가방의 무게보다 작거나 같으면 넣어보기.
//i-1아이템까지 넣은 가방에 이번꺼 넣어보기 vs 직전꺼 그대로 들고가기
D[i][w] = Math.max(D[i-1][w-weights[i]]+profits[i], D[i-1][w]);
}else { //가방에 넣지 못하는 상황.
//이번 물건이 가방 무게보다 무거우니까 직전 무게까지의 최적이 지금 최적 해
D[i][w] = D[i-1][w];
}
}
}
System.out.println(Arrays.toString(weights));
System.out.println(Arrays.toString(profits));
//최종. 가방 무게까지 모든 아이템 고려.
System.out.println(D[N][W]);
}
}
'알고리즘 > ETC' 카테고리의 다른 글
[DP] Floyd-Warshall (0) | 2021.04.02 |
---|---|
[DP] 다익스트라 (0) | 2021.04.02 |
[최소신장트리] PRIM (0) | 2021.04.01 |
[최소신장트리] Kruskal (0) | 2021.03.28 |
[최소신장트리] Union Find (0) | 2021.03.28 |
Comments