카테고리 없음

[알고리즘] DP 공부하기(4) - 백준 12865 평범한 배낭

lee_jy_1204 2024. 11. 12. 22:05
작성자 이재영
일 시 2024. 11. 12 (화) 18:00 ~ 21:00
장 소 복지관 B-128-1호
참가자 명단 임혜진,  장원준, 이재영, 성창민, 김명원
 사 진

이번 모각코에서는 백준 골드 수준의 DP 문제를 풀어보았다. 앞으로 어려운 문제를 대비하며 기초를 탄탄히 다지는 중이다. 다음은 이번에 풀어본 문제와 그 풀이 과정을 정리한 내용이다.

1. 백준 12865번 - 평범한 배낭 (0/1 Knapsack 문제)

문제

물건 N개가 있고, 각 물건은 무게 W와 가치 V를 가지고 있습니다. 배낭에는 최대 K의 무게까지 담을 수 있으며, 우리는 배낭에 담을 수 있는 물건들의 가치 합이 최대가 되도록 선택하고자 합니다.
즉, 물건을 적절히 선택하여 배낭에 담았을 때 얻을 수 있는 최대 가치를 구하는 문제입니다.

입력

첫 줄에 물건의 수 N과 배낭의 최대 무게 K가 주어집니다.
이후 N줄에는 각 물건의 무게 W와 가치 V가 주어집니다.

출력

배낭에 담을 수 있는 물건들의 가치 합의 최댓값을 출력합니다.

 

문제 분석 및 부분 문제 정의

이 문제는 0/1 배낭 문제로, 물건을 선택할 때 각 물건을 넣거나 넣지 않는 두 가지 선택지가 존재한다.
문제를 작은 부분 문제로 나누어 보면, i번째 물건까지 고려했을 때의 최대 가치를 찾는 것으로 나눌 수 있다.

 

점화식 도출

각 물건 i와 현재 배낭 무게 j를 기준으로 점화식을 도출할 수 있다.

  1. 물건 i를 배낭에 담지 않는 경우: dp[i][j] = dp[i-1][j]
  2. 물건 i를 배낭에 담는 경우 (단, j >= W일 때): dp[i][j] = dp[i-1][j-W] + V

즉, 각 경우를 비교하여 더 큰 값을 택하게 되면 최적해를 구할 수 있다.

 

초기 조건 설정

dp[i][j]는 i번째 물건까지 고려하고 j만큼의 무게를 허용할 때 얻을 수 있는 최대 가치이다.
초기에는 물건을 담지 않는 상태로 시작하기 때문에, 초기 상태로 dp[0][j] = 0으로 설정한다.

 

import sys
input = sys.stdin.readline

# N: 물건의 개수, K: 배낭의 최대 무게
N, K = map(int, input().split())
items = [tuple(map(int, input().split())) for _ in range(N)]

# dp 배열 초기화 (각 weight에 대해 최대 가치 저장)
dp = [0] * (K + 1)

for weight, value in items:
    for w in range(K, weight - 1, -1):
        dp[w] = max(dp[w], dp[w - weight] + value)

print(dp[K])

 

  • DP 배열 초기화: 최대 무게 K에 대해 각 무게별 최대 가치를 저장할 DP 배열을 초기화했다.
  • 역방향 반복: 무게별로 값을 갱신할 때, 역방향으로 갱신하여 현재 물건을 중복해서 담는 경우를 방지했다.
  • 최댓값 갱신: 각 무게에 대해 물건을 담는 경우와 담지 않는 경우의 가치를 비교해 최댓값을 갱신했다.

 

이 문제를 통해 0/1 배낭 문제의 DP 해결 방법을 복습할 수 있었다.
배낭 문제는 다양한 유형의 DP 문제에서 등장하기 때문에 반복적으로 풀어보는 것이 큰 도움이 되는 것 같다.