본문 바로가기
백준

[12865번] 평범한 배낭

by 2744m 2020. 8. 4.

배낭(Knapsack) 문제 중 짐(item)을 쪼갤 수 없는 0-1 냅색 문제

DP(동적계획법)의 대표적 문제 중 하나

입력은 N(item의 개수), K(배낭의 최대 무게)와
각 item의 w(무게), v(가치)이다.

입력을 바탕으로 배낭에 넣은 물건의 가치의 합이 최대가 되도록 한다.

점화식을 세워보면 아래와 같이 나타낼 수 있다.

DP( i, w ) = | max( DP( i, w ) , DP[ w - item[i].weight ] + item[i].value ] ) ( item[i].weight <= w )

                | DP( i, w) ( item[i].weight > w )

( i : 현 아이템 번호, w : 현 배낭의 무게 )

여기서 w를 최대 K부터 1까지 줄여가면서 배낭을 채워나가고 현 아이템에 대해 기록이 끝났다면 다음 아이템으로 넘어가서 반복하도록 한다.

예시로,
4 7 // N K
6 13
4 8
3 6
5 12
란 입력이 들어오게 되면 아래와 같이 저장하고 DP(가방) 배열을 채워 나간다.

1번 item -> weight : 6 , value : 13

2번 item -> weight : 4 , value : 8

3번 item -> weight : 3 , value : 6

4번 item -> weight : 5 , value : 12

step 1) 1번 item

무게가 7인 가방을 1번 item만으로 채울 수 있는 최대 가치는 13

무게가 6인 가방을 1번 item만으로 채울 수 있는 최대 가치는 13 

무게가 5인 가방을 1번 item만으로 채울 수 있는 최대 가치는 0 ....

 

step 2) 2번 item

무게가 7인 가방을 2번 item과 1번 item으로 채울 수 있는 최대 가치는

step1의 7번 arr의 13 vs item_2의 가치 8 + 남은 무게(3)의 가치 0를 비교해서 최대 가치인 13을 저장

....

무게가 5인 가방을 2번 1번 item으로 채울 수 있는 최대 가치는

step1의 5번 arr의 0 vs item_2의 가치 8 + 남은 무게(1)의 가치  0을 비교해서 최대 가치인 8을 저장

 

이런식으로 DP배열을 채워나가면 최종적으로 DP[K]의 값이 내가 구할 답이된다.

 

각 step을 진행 할 때 마다 기록되는 숫자는 이전 item의 정보도 담고 있기 때문에 1차원 배열로 충분히 처리할 수 있다.



 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <stdio.h>
#include <algorithm>
using namespace std;
int N, K;
struct info { int weight, value; }item[105];
int DP[100005];
 
int main() {
    scanf("%d %d"&N, &K);
    for (int i = 1; i <= N; i++) {
        int w, v;
        scanf("%d %d"&w, &v);
        item[i] = { w,v };
    }
 
    for (int I_idx = 1; I_idx <= N; I_idx++) {
        for (int w = K; w >= 1; w--) { // w : 현재 사용할 수 있는 배낭의 무게(공간)
            int tmp = DP[w - item[I_idx].weight]; //현재 아이템을 넣었을 때 남은 공간이 가지는 최대 가치
            DP[w] = item[I_idx].weight <= w ? max(DP[w], tmp + item[I_idx].value) : DP[w];
        }
    }
 
    printf("%d", DP[K]);
    return 0;
}
cs

'백준' 카테고리의 다른 글

[2749번] 피보나치 수3  (0) 2020.04.04
[1922번] 네트워크 연결  (0) 2019.08.15
[1708번] 볼록 껍질(Convex Hull)  (0) 2019.08.13
[11758번] ccw  (0) 2019.08.13
[2133번] 타일 채우기  (0) 2019.06.11

댓글