1202 보석 도둑
1202. 보석 도둑 / c++ / Gold2 / 55분
문제
https://www.acmicpc.net/problem/1202
- N개의 보석과 K개의 가방이 주어진다. (1 <= N,K <= 300’000)
- 각 보석은 M의 무개와 V의 가치를 지닌다. (0 <= M,V <= 1’000’000)
- 각 가방은 최대 C의 무게까지 담을 수 있다. (1 <= C <= 100’000’000)
- 하나의 가방에 하나의 보석밖에 넣지 못할 때, 담을 수 있는 보석의 최대 가치는?
접근 방식
자료구조, 그리디, 우선순위 큐
- 매번 가치가 최고인 것을 골라야 하니 그리디 알고리즘을 이용할 수 있다.
- 그리디 = 우선순위 큐 라고 봐도 될 정도로 활용성이 좋아서 우선순위 큐를 이용했다.
- 가방을 무게가 작은순으로 순회하면서, 자신보다 무게가 가벼운 보석들을 우선순위 큐에 다 담는다.
- 그리고 그 중 가장 가치가 높은 보석을 고른다.
문제 풀이
#pragma GCC optimize("Ofast")
#include <iostream>
#include <queue>
#include <algorithm>
using namespace std;
int N, K, M, V;
vector<pair<int, int>> jewels;
vector<int> bags;
unsigned long long answer = 0;
priority_queue<int> trashBag;
int main()
{
ios::sync_with_stdio(0); cin.tie(0);
cin >> N >> K;
while (N-- > 0)
{
cin >> M >> V;
jewels.push_back({ M, V });
}
sort(jewels.begin(), jewels.end());
while (K-- > 0)
{
cin >> M;
bags.push_back(M);
}
sort(bags.begin(), bags.end());
int jewelsPos = 0;
for (int i = 0; i < bags.size(); ++i)
{
while (jewelsPos < jewels.size())
{
if (jewels[jewelsPos].first <= bags[i])
{
trashBag.push(jewels[jewelsPos++].second);
}
else break;
}
if (!trashBag.empty())
{
answer += trashBag.top(); trashBag.pop();
}
}
cout << answer << '\n';
return 0;
}
다시 생각해 볼 점
- 처음엔 보석과 가방을 모두 우선순위 큐로 처리했었다. 그럴 필요가 없었다. 꼭 필요한 것만 우선순위 큐를 사용하고, 자료구조를 남용하지 말자.
- ‘현재 가방보다 무게가 가장 작은 것 중 가장 높은 가치의 보석’ 이 이번 문제의 핵심이었다. 핵심 키워드를 정확히 정해놓으면 문제 풀기가 더 수월할 것 같다.