한 줄 해설과 용량별 DP 변화 중심으로 정리한 상세형 버전이다.
1. 문제를 아주 짧게 말하면
무게 제한 K 안에서 여러 물건 중 일부를 골라 담을 때 얻을 수 있는 가치의 최댓값을 구하는 전형적인 0/1 배낭 문제다. 물건은 각각 한 번만 사용할 수 있다. [Source](https://www.acmicpc.net/problem/12865)
2. 핵심 아이디어
dp[i][cap]의 뜻
앞에서 i개 물건만 고려했을 때, 가방 용량 cap으로 얻을 수 있는 최대 가치
- 현재 물건을 안 넣으면:
dp[i-1][cap] - 현재 물건을 넣으면:
dp[i-1][cap-weight] + value
3. 전체 코드
1import sys
2
3input = sys.stdin.readline
4n, k = map(int, input().split())
5items = [tuple(map(int, input().split())) for _ in range(n)]
6
7dp = [[0] * (k + 1) for _ in range(n + 1)]
8
9for i in range(1, n + 1):
10 weight, value = items[i - 1]
11 for cap in range(1, k + 1):
12 if cap < weight:
13 dp[i][cap] = dp[i - 1][cap]
14 else:
15 dp[i][cap] = max(dp[i - 1][cap], dp[i - 1][cap - weight] + value)
16
17print(dp[n][k])
4. 코드 한 줄씩 설명
| 줄 | 코드 | 설명 |
|---|---|---|
| 3 | input = sys.stdin.readline |
input 함수를 sys.stdin.readline으로 바꿔 입력 속도를 높인다. |
| 4 | n, k = map(int, input().split()) |
물건 개수 n과 배낭 허용 무게 k를 입력받는다. |
| 5 | items = [tuple(map(int, input().split())) for _ in range(n)] |
각 물건의 (무게, 가치)를 리스트에 저장한다. |
| 7 | dp = [[0] * (k + 1) for _ in range(n + 1)] |
dp[i][cap]는 앞에서 i개 물건만 고려했을 때 용량 cap으로 만들 수 있는 최대 가치를 뜻한다. |
| 9 | for i in range(1, n + 1): |
첫 번째 물건부터 차례대로 고려한다. |
| 10 | weight, value = items[i - 1] |
현재 살펴보는 물건의 무게와 가치를 꺼낸다. |
| 11 | for cap in range(1, k + 1): |
현재 용량을 1부터 k까지 바꿔 가며 계산한다. |
| 12 | if cap < weight: |
현재 용량이 물건 무게보다 작으면 이 물건은 넣을 수 없다. |
| 13 | dp[i][cap] = dp[i - 1][cap] |
넣을 수 없으니 바로 위 행의 값, 즉 이전 물건들만 고려한 최적값을 그대로 가져온다. |
| 14 | else: |
현재 물건을 넣을 수 있는 경우다. |
| 15 | dp[i][cap] = max(dp[i - 1][cap], dp[i - 1][cap - weight] + value) |
안 넣는 경우와 넣는 경우를 비교해 더 큰 가치를 선택한다. |
| 17 | print(dp[n][k]) |
모든 물건을 고려했을 때 용량 k에서의 최대 가치가 정답이다. |
5. DP 테이블 시각화
이해용 예시로 물건 (6,13), (4,8), (3,6), (5,12), 용량 7을 사용했다.
| 물건 \ 용량 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
|---|---|---|---|---|---|---|---|---|
| 0개 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 1개 | 0 | 0 | 0 | 0 | 0 | 0 | 13 | 13 |
| 2개 | 0 | 0 | 0 | 0 | 8 | 8 | 13 | 13 |
| 3개 | 0 | 0 | 0 | 6 | 8 | 8 | 13 | 14 |
| 4개 | 0 | 0 | 0 | 6 | 8 | 12 | 13 | 14 |
6. 물건이 하나씩 추가될 때 배열 변화
물건 1: 무게 6, 가치 13
이 물건까지 고려한 뒤 각 용량에서 얻을 수 있는 최대 가치
dp[1] = [0, 0, 0, 0, 0, 0, 13, 13]
물건 2: 무게 4, 가치 8
이 물건까지 고려한 뒤 각 용량에서 얻을 수 있는 최대 가치
dp[2] = [0, 0, 0, 0, 8, 8, 13, 13]
물건 3: 무게 3, 가치 6
이 물건까지 고려한 뒤 각 용량에서 얻을 수 있는 최대 가치
dp[3] = [0, 0, 0, 6, 8, 8, 13, 14]
물건 4: 무게 5, 가치 12
이 물건까지 고려한 뒤 각 용량에서 얻을 수 있는 최대 가치
dp[4] = [0, 0, 0, 6, 8, 12, 13, 14]
7. 중요한 칸 직접 따라가기
dp[1][6] = 13
용량 6에서 첫 물건을 담으면 13, 안 담으면 0이므로 13 선택
dp[2][4] = 8
용량 4에서 두 번째 물건만 담을 수 있어 8 선택
dp[3][7] = 14
용량 7에서 세 번째 물건(3,6)을 담고 남은 4칸 가치 8을 더해 총 14가 가능
dp[4][7] = 14
용량 7에서 네 번째 물건을 담으면 dp[3][2]+12=12, 안 담으면 14라서 그대로 14 유지
8. 자주 헷갈리는 포인트
- 이 문제는 0/1 배낭이라 같은 물건을 여러 번 쓰면 안 된다.
- 현재 행에서 현재 행을 참조하면 중복 사용 문제가 생긴다. 그래서 2차원 DP는 항상 위 행을 본다.
- 최대 가치 문제지, 물건 개수를 최대화하는 문제가 아니다.
9. 복잡도
시간 복잡도는 O(NK) 이다.
공간 복잡도도 2차원 DP 기준 O(NK) 이다.
원문 문제 링크
'크래프톤 정글 > 정글에서 문제풀기' 카테고리의 다른 글
| [정글 알고리즘] - [중] 백준9084- 동전- 골드5 (0) | 2026.03.28 |
|---|---|
| [정글 알고리즘] - [중] 백준2253- 점프- 골드4 (1) | 2026.03.28 |
| [정글 알고리즘] - [중] 백준9251- LCS- 골드5 (0) | 2026.03.28 |
| [정글 알고리즘] - [하] 백준11047- 동전 0- 실버4 (0) | 2026.03.28 |
| [정글 알고리즘] - [하] 백준1541- 잃어버린 괄호- 실버2 (0) | 2026.03.28 |