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
문제 개요
동적 계획법에서 유명한 문제인 배낭 문제이다.
일반적으로 푼다면 전체 2^n 의 경우의 수가 나오는데
물품을 가져갈지, 가져가지 않을지 두 가지 중에서 가치합이 큰 경우를 골라주는 알고리즘을 구현하면 된다.
물품을 가져가지 않을 경우
pack(남은 용량, 물품 수 +1)
물품을 가져가는 경우
pack(남은 용량 - 선택 물품의 용량, 물품 수 +1) + 가치 v값
이 경우를 저장하여 메모이제이션을 이용해 주면 된다.
max(물품을 가져가지 않을 경우, 물품을 가져가는 경우 + 물품의 가치)
코드
함수의 시작은 최대 용량인 k와 물품이 0개부터 시작하기에 pack(k, 0)으로 해주면 된다.
최대 물품 용량이나 가치의 합이 int형의 크기를 넘지 않기에 따로 생각하지 않아도 된다.
#include <bits/stdc++.h>
using namespace std;
int n, k;
int volume[100], need[100];
int cache[100001][100];
// capacity 남은 용량, item 물품 수
int pack(int capacity, int item) {
// 물품을 다 넣을 경우
if (item == n) return 0;
int& ret = cache[capacity][item];
if (ret != -1) return ret;
// 물품 안 넣는 경우
ret = pack(capacity, item+1);
// 물품 넣을 경우 (남은 용량이 크거나 같을 때)
if (capacity >= volume[item]) {
ret = max(ret, pack(capacity-volume[item], item+1) +
need[item]);
}
return ret;
}
int main(void) {
cin >> n >> k;
for (int i = 0; i < n; i++) {
cin >> volume[i] >> need[i];
}
// fill [행 크기 최대-1][열 크기 최대]
fill(&cache[0][0], &cache[100000][100], -1);
cout << pack(k, 0);
}
'알고리즘 > 동적 계획법' 카테고리의 다른 글
(c++) 동적계획법 BOJ 1520번: 내리막 길 (0) | 2024.01.22 |
---|---|
(c++) 동적계획법 BOJ 11049번: 행렬 곱셈 순서 (0) | 2024.01.21 |
(c++) BOJ 9251번: LCS (0) | 2024.01.18 |
(c++) LIS BOJ 2565번: 전깃줄 (0) | 2024.01.18 |
(c++) 11054번: 가장 긴 바이토닉 부분 수열 (0) | 2024.01.16 |
댓글