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
#include <iostream>
using namespace std;
int main() {
int n, k;
int w[101] = { 0, };
int v[101] = { 0, };
int dp[101][100001] = { 0, };
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++) {
if (w[i] <= j) {
dp[i][j] = max(dp[i - 1][j], v[i] + dp[i - 1][j - w[i]]);
}
else
dp[i][j] = dp[i - 1][j];
}
}
cout << dp[n][k] << endl;
return 0;
}
배낭 문제이며, 점화식은 다음과 같다.
dp[i][j] = max(dp[i -1][j], DP[i - 1][j - W[i]] + V[i]);
여기서 i는 배낭에 넣을 물건 번호, j는 현재 배낭의 무게를 의미한다.
예시 입력으로 만들어진 dp를 살펴보면 (물건 4개의 무게/가치가 6/13, 4/8, 3/6, 5/12)
dp[i][j] | [ ][1] | [ ][2] | [ ][3] | [ ][4] | [ ][5] | [ ][6] | [ ][7] |
[1][ ] | 0 | 0 | 0 | 0 | 0 | 13 | 13 |
[2][ ] | 0 | 0 | 0 | 8 | 8 | 13 | 13 |
[3][ ] | 0 | 0 | 6 | 8 | 8 | 13 | 14 |
[4][ ] | 0 | 0 | 6 | 8 | 12 | 13 | 14 |
1번 물건의 무게는 6, 가치는 13이다. 그리고 j는 1에서 7까지 변하는데 j가 늘어날수록 가방의 크기가 커진다고 생각해보자. 1번 물건을 넣어야 할 때 가방의 크기가 6 즉, j=6일때 비로소 1번 물건을 넣을 수 있고 dp[1][6]은 13으로 업데이트된다. 그리고 dp[1][7]일때 dp[1][7-(1번 물건의 무게)] = dp[1][1]은 0이므로 다음 i는 2로 넘어간다.
2번 물건의 무게는 4, 가치는 8이다. j가 늘어나면서 가방의 크기가 4가 되었을 때 2번 물건을 넣을 수 있고 dp[2][4]의 값은 0이었으므로 2번 물건의 가치인 8로 업데이트해준다. 그리고 가방 크기가 6이 되었을 때 2번 물건을 넣어놓은 것보다 1번 물건을 넣어놓은 것이 가치가 더 크므로 dp[2][6]은 13이다.
이런 식으로 dp값을 구해주는데 이 중에서 dp[3][7]를 살펴보면 dp[3][7]은 dp[2][7]과 dp[3][7-(3번 물건의 무게)] + v[3] 둘 중 큰 값을 저장한다. dp[3][4]값은 6이고 v[3]은 8이므로 최종적으로 dp[2][7]은 13, dp[3][7]은 14이므로 dp[3][7]에는 14가 저장된다.
1번부터 N번 물건까지 모두 넣어봤을 때 가치합이 가장 큰 값 = dp[N][K]는 2, 3번 물건을 넣은 14가 답이다.
'Algorithm > BAEKJOON' 카테고리의 다른 글
[BOJ] 1991번 트리 순회 (C++) (0) | 2021.11.06 |
---|---|
[BOJ] 21736번 헌내기는 친구가 필요해 (C++) (0) | 2021.11.05 |
[BOJ] 1966번 프린터 큐 (C++) (0) | 2021.11.03 |
[BOJ] 4963번 섬의 개수 (C++) (0) | 2021.11.03 |
[BOJ] 1012번 유기농 배추 (C++) (0) | 2021.11.02 |