본문 바로가기
문제 풀이/백준(BOJ)

[C++] 백준 12865번 : 평범한 배낭

by 희조당 2021. 6. 25.
728x90

https://www.acmicpc.net/problem/12865

 

12865번: 평범한 배낭

첫 줄에 물품의 수 N(1 ≤ N ≤ 100)과 준서가 버틸 수 있는 무게 K(1 ≤ K ≤ 100,000)가 주어진다. 두 번째 줄부터 N개의 줄에 거쳐 각 물건의 무게 W(1 ≤ W ≤ 100,000)와 해당 물건의 가치 V(0 ≤ V ≤ 1,000)

www.acmicpc.net


문제 풀이

 배열 DP[i][j]는 가방이 j 무게 일 때 i 번째 물건까지 확인했을 때의 최대 가치이다.

예를 들어서 DP[3][5]는 무게 5인 가방에 대해서 3번째 물건까지 확인했을 때의 최대가치이다.

경우는 단순하게 2가지로 i번째 물건을 담았을 때와 담지 않았을 때로 나뉜다.

표를 통해서 이해하면 매우 쉽다. (문제 참고!)

  0 1 2 3 4
0 0 0 0 0 0
1 0 0 0 0 0
2 0 0 0 0 0
3 0 0 0  6  6
4 0 0 8 8 8
5 0 0 8 8 12
6 0 13 13 13 13
7 0 13 13  14  14

가로는 가방의 무게를 나타내고, 세로는 i 번째 물건이다. 가장 중요한 점화식은

i번째 물건을 담을 때 : DP[i][j] = i번째 물건의 가치 + DP[i-1][j - i번째 물건의 무게]와 DP[i-1][j] 중 최댓값

i번째 물건을 담지 않을 때 : DP[i][j] = DP[i-1][j]

여기서 DP[i-1][j - i번째 물건의 무게] 가 가장 중요하다. 표에서 강조한 부분을 보면 바로 이해할 수 있다.

무게가 7인 배낭을 만들 때 무게가 3과 4인 물건을 넣을 수도 있고 그냥 무게가 6인 물건만 넣을 수 있다.

여기서 max함수를 통해서 가치가 최대인 값을 비교해서 대입하는데 DP[i-1][j - i번째 물건의 무게] 이 점화식이 무게가  3인 상태에서 무게가 4인 물건을 추가로 집어넣을 때를 의미한다!

느낀 점

다이나믹 프로그래밍1의 마지막 문제인데 접근을 아직도 어려워한 거 같아서 약간 좌절한 문제였다. 따로 익숙해질 시간이 필요한 문제인 것 같다.

코드

#include <iostream>
#include <algorithm>
using namespace std;

int n, k;
int DP[101][100001];
int w[101];
int v[101];

int main() {
	cin >> n >> k;
	for (int i = 1; i <= n;i++) {
		cin >> w[i] >> v[i];
	}
	for (int i = 1; i <= n;i++) {
		for (int j = 1; j <= k;j++) {
			DP[i][j] = DP[i - 1][j];
			if (j - w[i] >= 0) 
				DP[i][j] = max(DP[i - 1][j], v[i] + DP[i - 1][j-w[i]]);
		}
	}
	cout << DP[n][k];
}

'문제 풀이 > 백준(BOJ)' 카테고리의 다른 글

[C++] 백준 1931번 : 회의실 배정  (0) 2021.06.27
[C++] 백준 11047번 : 동전 0  (0) 2021.06.26
[C++] 백준 1912번 : 연속합  (0) 2021.06.25
[C++] 백준 9251번 : LCS  (0) 2021.06.25
[C++] 백준 2565번 : 전깃줄  (0) 2021.06.23

댓글