문제
세계적인 도둑 상덕이는 보석점을 털기로 결심했다.
상덕이가 털 보석점에는 보석이 총 N개 있다. 각 보석은 무게 Mi와 가격 Vi를 가지고 있다. 상덕이는 가방을 K개 가지고 있고, 각 가방에 담을 수 있는 최대 무게는 Ci이다. 가방에는 최대 한 개의 보석만 넣을 수 있다.
상덕이가 훔칠 수 있는 보석의 최대 가격을 구하는 프로그램을 작성하시오.
입력
첫째 줄에 N과 K가 주어진다. (1 ≤ N, K ≤ 300,000)
다음 N개 줄에는 각 보석의 정보 Mi와 Vi가 주어진다. (0 ≤ Mi, Vi ≤ 1,000,000)
다음 K개 줄에는 가방에 담을 수 있는 최대 무게 Ci가 주어진다. (1 ≤ Ci ≤ 100,000,000)
모든 숫자는 양의 정수이다.
출력
첫째 줄에 상덕이가 훔칠 수 있는 보석 가격의 합의 최댓값을 출력한다.
예제 입력 1
2 1
5 10
100 100
11
예제 출력 1
10
예제 입력 2
3 2
1 65
5 23
2 99
10
2
예제 출력 2
164
원리
보석 목록과 가방 목록을 무게 순으로 정렬한 뒤, 모든 가방들을 순회하면서 그 가방의 용량보다 작은 보석들만 우선순위 큐에 넣고 하나 씩 pop하면 된다.
요점은 보석 목록을 한 번만 순회하는 것.
시행착오
처음엔 가방을 순회할 때 마다 매번 가방에 들어갈 수 있는 보석들을 전부 순회해서 그중 가장 큰 값을 구하려고 했다.
그러나 보석들을 한 번씩만 확인해도 가능한 문제였음을 알았다.
풀이
#include <iostream>
#include <vector>
#include <algorithm>
#include <queue>
using namespace std;
int main() {
ios_base::sync_with_stdio(0);
cin.tie(0);
int N, K;
cin >> N >> K;
vector<pair<int, int>> gems;
vector<int> bags;
priority_queue<int> pq;
long long sum = 0;
for (size_t i = 0; i < N; i++)
{
int m, v;
cin >> m >> v;
gems.push_back(pair<int, int>(m, v));
}
for (size_t i = 0; i < K; i++)
{
int c;
cin >> c;
bags.push_back(c);
}
sort(gems.begin(), gems.end());
sort(bags.begin(), bags.end());
//for (iter = gems.begin(); iter != gems.end(); iter++) {
// cout << "[" << iter->first << ", " << iter->second << "]" << " ";
//}
int idx = 0;
for (size_t i = 0; i < K; i++)
{
/*for (size_t j = idx; j < N; j++)
{
if (gems[j].first > bags[i]) break;
pq.push(gems[i].second);
idx++;
}*/
while (idx < N && gems[idx].first <= bags[i])
{
pq.push(gems[idx++].second);
}
if (!pq.empty()) {
sum += pq.top();
pq.pop();
}
}
cout << sum;
cin >> N;
}
'수학, 알고리즘' 카테고리의 다른 글
[프로그래머스 Lv3] 셔틀버스 (0) | 2022.07.21 |
---|---|
[백준][문자열]Startlink Tower (0) | 2022.07.20 |
[백준][문자열] Contact (0) | 2022.07.20 |
[백준] ACM Craft (0) | 2022.07.20 |
[백준] 색종이 만들기 (0) | 2022.07.20 |