문제 링크: https://www.acmicpc.net/problem/1202
배낭 문제(knapsack problem)의 변형판입니다. DP를 사용할 필요가 없습니다. 그리디로 풀면 됩니다.
한 가방에 보석 한개밖에 못넣기 때문에 문제가 간단합니다.
일단 가방은 무게 오름차순으로, 보석은 가격 내림차순으로 정렬합니다.
가장 값나가는 보석부터 차례대로 넣습니다. 어느 배낭에 넣을지 결정하는 것이 문제인데요, 넣을 수 있는 가방 중에 용량이 가장 작은 걸 고르면 됩니다.
여기서 감이 오실텐데요, 이분탐색을 쓰면 됩니다.
lower_bound를 사용해 적당한 가방을 골라 넣습니다. 조건에 해당하는 가방이 없는 경우 (=용량이 제일 큰 가방보다 보석 무게가 더 무거운 경우) 체크해서 빼줍니다. 사용한 가방은 가방 목록에서 뺍니다.
가방 목록의 자료구조는 뭘 써야 할까요? vector는 erase할 때마다 재배열을 해줘야 하니 O(n)의 시간이 걸립니다. 그래서 set을 쓰면 삭제가 O(log n)이니 쓰면 될 것 같은데, 같은 용량을 가진 가방이 여러개 나올 수 있으니 multiset을 사용하면 됩니다.
multiset에서 lower_bound를 쓸 땐 multiset의 메소드 lower_bound를 써야 O(log n)의 시간이 걸립니다. lower_bound 함수를 쓰면 O(n)의 시간이 걸립니다. 그럼 이분탐색이 아니고 선형탐색이죠? iterator가 random access가 가능할 때만 O(log n)이 보장됩니다.
map, set, multiset 자료구조에서 이분탐색을 할 땐 꼭 메소드의 lower_bound, upper_bound를 사용해주세요.
#pragma GCC optimize ("Ofast")
#define _CRT_SECURE_NO_WARNINGS
#define _SILENCE_CXX17_C_HEADER_DEPRECATION_WARNING
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
#ifndef ONLINE_JUDGE
freopen("input.txt", "r", stdin);
//freopen("output.txt", "w", stdout);
#endif
ios_base::sync_with_stdio(false);
cin.tie(nullptr), cout.tie(nullptr);
int n, k;
cin >> n >> k;
vector<pair<int, int>> jewels(n); // cost(-), weight
for (auto& p : jewels) {
cin >> p.second >> p.first;
p.first = -p.first;
}
multiset<int> knapsacks;
for (int i = 0; i < k; ++i) {
int in;
cin >> in;
knapsacks.insert(in);
}
sort(jewels.begin(), jewels.end());
ll sum = 0;
for (auto [cost, weight] : jewels) {
cost = -cost;
auto it = knapsacks.lower_bound(weight);
if (it != knapsacks.end()) {
sum += cost;
knapsacks.erase(it);
if (knapsacks.empty()) break;
}
}
cout << sum << '\n';
return 0;
}
'Online Judge > 백준' 카테고리의 다른 글
[백준][C++] 1516: 게임 개발 (0) | 2020.07.31 |
---|---|
[백준][C++] 15824: 너 봄에는 캡사이신이 맛있단다 (0) | 2020.07.31 |
[백준][C++] 15658: 연산자 끼워넣기 (2) (0) | 2020.07.29 |
[백준][C++] 17406: 배열 돌리기 4 (0) | 2020.07.29 |
[백준][C++] 18891: 제21대 국회의원 선거 (0) | 2020.07.29 |