2 분 소요

1. Kanpsack Problem이란?

도둑이 보석가게에 배낭을 메고 침입했다. 배낭의 최대 용량은 W이며, 이를 초과해서 보석을 담으면 배낭이 찢어질 것이다. 각 보석들의 무게와 가격은 알고 있다. 배낭이 찢어지지 않는 선에서 가격 합이 최대가 되도록 보석을 담는 방법은?

배낭 채우기 문제는 2가지로 나뉘는데 보석을 자를 수 있다고 가정하는 Fraction Knapsack 문제와 자를 수 없다고 가정하는 0-1 Knapsack 문제가 있다.
0-1 Kanpsack 문제는 다이나믹 프로그래밍이라는 방법을 쓰는 기본적인 문제로 알려져 있다. 이 문제를 보면 생각나는 방법이 두 가지 정도가 있다.

1.1 모든 경우의 수를 넣어본다 (Brute-Force)

n개의 보석이 있다고 치면, n개의 보석으로 만들 수 있는 가능한 부분집합의 수는 $2^n$개이다. 최악의 경우에는 $2^n$번까지 봐야 한다. 즉 $O(2^n)$의 시간복잡도가 나온다.

1.2 가치가 제일 높은 보석(Greedy)

  • 1.2.1 가격이 제일 높은 보석

    (4kg, $6), (4kg, $7), (2kg, $4), (1kg, $3), (6kg, $9), (3kg, $5)를 만족하는 보석들이 있고 가방의 한도는 10kg이라고 가정하자

가격이 제일 높은 보석을 먼저 고르는 방법을 쓴다고 하면, (4kg, $7), (6kg, $9)를 고를 것이다. 그러면 10kg이 되고 가격의 합은 $16이 된다.
하지만 (4kg, $6), (4kg, $7), (2kg, $4)를 고르면 10kg/$17이 된다는 것을 알 수 있다. 즉 이 방법은 최적의 답을 보장하지 못한다.

  • 1.2.2 (가격/무게)의 값이 제일 높은 보석

    W = 30kg
    보석1 : 5kg $\div$ $5 -> kg당 $1
    보석2 : 10kg $\div$ $6 -> kg당 $0.6
    보석3 : 20kg $\div$ $14 -> kg당 $0.7

이 경우에 무게당 가격 순으로 보석을 넣으면 보석1, 보석3이 들어가며 가격의 합은 $19이다. 그런데 배낭 무게가 5kg이 남는다. 보석2를 넣을 수는 없으므로 5kg은 남는 공간이 된다. 보석2, 보석3 을 넣으면 30kg/$20 가 된다.

이처럼 특정한 기준을 정해놓고 그 기준의 값이 가장 높은 순으로 집는 걸 Greedy 알고리즘이라고 하는데 0-1 배낭 채우기 문제는 Greedy한 방법으로는 풀 수 없는 문제이다.
Fraction Knapsack 문제는 Greedy로 풀 수 있다. 위 예시에서 보석2를 반으로 잘라서 남은 5kg짜리 공간에 넣으면 그게 최적의 답이 된다.

2. DP 적용

0-1 배낭 채우기 문제를 푸는데 DP가 적용된다.

  • 집합 A가 n번째 보석을 포함하고 있지 않다면 A는 n번째 보석을 뺀 나머지 n-1개의 보석들 중에서 최적으로 고른 부분집합과 같다.
  • 집합 A가 n번째 보석을 포함하고 있다면, A에 속한 보석들의 총 가격은 n-1개의 보석들 중에서 최적으로 고른 가격의 합에다가 보석 n의 가격을 더한 것과 같다. (단 n번째 보석을 넣었을 때 배낭이 터지지 않아야 한다.)

이 내용을 점화식으로 작성하면 아래와 같다

$P[i,w]$ =
if $(\; w_i > w,) \quad P[i-1, w]$
else, $P[i,w] = max [ v_i + P[i-1, w - w_k], P[i-1, w] ]$

P[i,w]란 i개의 보석이 있고 배낭의 무게 한도가 w일 때 최적의 이익을 의미한다. 식을 문장으로 풀면 아래와 같다.

  • i번째 보석이 배낭의 무게한도보다 무거우면 넣을 수 없으므로 i번째 보석을 뺀 i-1개의 보석들을 가지고 구한 전 단계의 최적값ㅇ르 가져온다
  • 그렇지 않은 경우, i번째 보석을 위해 i번째 보석만큼의 무게를 비웠을 때의 최적값에 i번째 보석의 가격을 더한 값 or i-1개의 보석들을 가지고 구한 전 단계의 최적값 중 큰 것을 선택한다.

P라는 2차원 리스트를 채워나가면서, 필요한 경우 “앞에서 계산했던 값을 이용해서” 다음 값을 계한다. 따라서 이게 DP문제인 것이다.

Ref.

Knapsack Problem\

카테고리:

업데이트: