Algorithm/백준

*[백준][1202] 보석 도둑

1일1코딩 2021. 4. 21. 23:04

www.acmicpc.net/problem/1202

 

1202번: 보석 도둑

첫째 줄에 N과 K가 주어진다. (1 ≤ N, K ≤ 300,000) 다음 N개 줄에는 각 보석의 정보 Mi와 Vi가 주어진다. (0 ≤ Mi, Vi ≤ 1,000,000) 다음 K개 줄에는 가방에 담을 수 있는 최대 무게 Ci가 주어진다. (1 ≤ Ci

www.acmicpc.net

문제

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

상덕이가 털 보석점에는 보석이 총 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. 가방의 무게도 오름차순으로 정렬을 하였다.

3. 현재 가방의 무게에 담을 수 있는 보석들을 모두 priority_queue에 담았다. pq의 root에는 젤 비싼 보석이 위치하게 된다.  또 한 다음 가방의 최고 가격의 보석을 찾을 때도 이전에 담아둔 pq에 누적되어 root값을 취하면 된다.

이 말은 다음 가방의 무게가 더 많이 담을 수 있으므로, 이전에 가방에서 채운 보석은 다시 찾기 않아도 되는 것이다.

4. 이러한 순서대로 가방 갯수 만큼 최고 가격의 보석을 채워 넣어 해결하였다.

 

소스코드

더보기
#include<stdio.h>
#include<vector>
#include<algorithm>
#include<queue>
using namespace std;
typedef unsigned long long ull;
bool cmp(pair<int, int> p1, pair<int, int> p2) {
	//보석 무게 오름차순
	return p1.first < p2.first;
}

int main()
{
	int N, K; //N = 보석 수, K = 가방 수
	ull answer = 0;
	vector<pair<int, int>> jewelry;
	vector<int> bags;
	priority_queue<int> pq;
	scanf("%d %d", &N, &K);
	for (int i = 0; i < N; i++) {
		int m, v;
		scanf("%d %d", &m, &v);
		jewelry.push_back(make_pair(m, v));
	}
	for (int i = 0; i < K; i++) {
		int n;
		scanf("%d", &n);
		bags.push_back(n);
	}
	sort(jewelry.begin(), jewelry.end(), cmp); //보석 무게 오름차순
	sort(bags.begin(), bags.end()); //가방 무게 오름차순
	int jewelryIndex = 0;
	for (int i = 0; i < K; i++) {
		int w = bags[i];
		while (jewelryIndex < N && w >= jewelry[jewelryIndex].first) {
			pq.push(jewelry[jewelryIndex].second);// 보석의 무게만 담음
			jewelryIndex++;
		}
		
		if (!pq.empty()) {
			answer += pq.top(); pq.pop();
		}
	}
	printf("%llu\n", answer);
}

 

결과