1202 보석도둑

10543 단어 greedybaekjoonbaekjoon

1202 보석 도둑

난이도: 하
링크: https://www.acmicpc.net/problem/1202
문제번호: 1202
생성일: 2021년 5월 18일 오후 10:02
유형: Greedy, 스택/큐
출처: https://jaimemin.tistory.com/760

문제

세계적인 도둑 상덕이는 보석점을 털기로 결심했다.

상덕이가 털 보석점에는 보석이 총 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)

모든 숫자는 양의 정수이다.

출력

첫째 줄에 상덕이가 훔칠 수 있는 보석 가격의 합의 최댓값을 출력한다.

풀이

그리디(Greedy)알고리즘과 우선순위 큐(Prioirty Queue)를 사용해서 가방에 담은 보석을 다시 검사하지 않는것이 핵심.

처음에는 보석의 입력이 (무게, 가치) 순 인 것을 보고 map 자료구조를 활용해서 입력과 동시에 정렬을 하려 하였으나, 삽입의 건 수가 최대 1,000,000 임으로 시간 초과가 나버린다.

보석과 가방을 모두 무게(용량)이 낮은 순으로 정렬하고 용량이 적은 가방부터 차례로 반복문을 돈다.

아래 그림을 예시로 들면,

  1. 가방 용량 4 임으로, 보석중에서 무게(W) 4 이하인 보석 (gem[1],gem[2]) 을 선택
  2. 선택된 보석의 가치(V)를 priority_queue에 삽입한다.
  3. 우선순위 큐(MAX HEAP)임으로 가장 가치가 높은 99top 에 위치하게 된다
  4. top 의 가치를 정답에 더한다.
  5. 이미 담은 보석임으로 우선순위 큐에서 pop 한다.
  6. 그 다음 가방도 (1~5)과정을 반복한다.

이렇게 하면 각 가방마다 현재 용량에서 담을 수 있는 최대 가치의 보석을 담게 된다.

코드

#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>

using namespace std;
int N, K;
priority_queue<int> pq;
vector<int>bag;
vector<pair<int, int>> jam;
int main() {
	cin.tie(0);
	cin.sync_with_stdio(0);
	cin >> N >> K;
	for (int i = 0; i < N; i++) {
		int w, v; cin >> w >> v;
		jam.push_back({ w,v });
	}
	for (int i = 0; i < K; i++) {
		int w; cin >> w; bag.push_back(w);
	}
	sort(jam.begin(), jam.end()); //보석을 무게 낮은순으로
	sort(bag.begin(), bag.end()); //가방 역시 무게용량 낮은순으로
	int idx = 0; long long ans = 0;
	for (int i = 0; i < K; i++) { //제일 용량 낮은 가방부터 시작하여 작은 가방에 가능한 최고 값어치를 담는 방법
		while (idx < N && jam[idx].first <= bag[i]) {
			pq.push(jam[idx++].second); // 가방에 담을수 있는 보석이면 pq 에 담음
		}//idx로 보석 전체 한번씩만 검사됨
		if (!pq.empty()) {
			ans += 1LL * pq.top(); // pq 가장 상단의 최고 가치 보석이 정답에 포함됨
			pq.pop();
		}
	}
	cout << ans << "\n";
	
	return 0;
}

좋은 웹페이지 즐겨찾기