어떤 문제를 푸는가
용량이 \(W\)인 가방에, 무게 \(w_i\)와 가치 \(v_i\)를 가진 물건들을 넣어 가치 합을
최대화 합니다. 각 물건은 넣거나 안 넣거나 둘 중 하나(0/1 배낭). 그리디로
"가치/무게 비율이 높은 것부터"는 0/1에서는 틀립니다. 반례가 쉽게 나옵니다.
상태 정의
DP의 출발은 항상 "상태가 무엇을 뜻하는가"입니다.
$$ dp[i][c] = \text{앞에서 } i \text{개의 물건만 고려하고, 용량이 } c \text{일 때 최대 가치} $$
점화식
\(i\)번째 물건을 볼 때 선택지는 둘입니다.
- 안 넣는다 —
dp[i-1][c]그대로. - 넣는다 (단, \(c \ge w_i\)일 때) —
dp[i-1][c - w_i] + v_i.
$$ dp[i][c] = \max\bigl(dp[i-1][c],\ dp[i-1][c - w_i] + v_i\bigr) $$
기저는 dp[0][c] = 0 (물건이 없으면 가치 0). 답은 dp[N][W] 입니다.
왜 옳은가
각 물건에 대한 결정은 이전 물건들의 최적해와 독립적 입니다. "i-1개까지의
최적 가치"를 알고 있으면, i번째를 넣을지 말지만 비교하면 됩니다. 부분 문제의
최적해가 전체의 최적해를 이룬다는 최적 부분 구조가 성립하므로 DP가
유효합니다. 또한 같은 (i, c) 상태가 여러 경로에서 재등장하므로 겹치는
부분 문제 도 만족합니다.
복잡도
상태가 \(N \times W\)개, 전이가 \(O(1)\)이므로
$$ O(N \cdot W) $$
이것은 입력 크기 \(N\)에 대해서는 다항이지만 용량 \(W\)의 값 에 비례하므로
엄밀히는 의사 다항(pseudo-polynomial)입니다. \(W\)가 아주 크면 이 방법은 못 씁니다.
변형 미리보기
| 종류 | 차이 |
|---|---|
| 0/1 배낭 | 각 물건 1개 |
| 무한(완전) 배낭 | 같은 물건 무제한 |
| 개수 제한 배낭 | 물건 \(i\)를 최대 \(k_i\)개 |
핵심 점화식은 같고, 순회 방향과 갱신 출처 만 달라집니다. 다음 강의에서
1차원 배열로 압축하는 핵심 기교와 변형 구현을 봅니다.