[백준 1202번 C/C++] 보석 도둑
[백준 1202번 C/C++] 보석 도둑
https://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
해결전략
그리디 알고리즘 Greedy Algorithm
우선순위 큐 Priority Queue
멀티 셋 Multi Set
그리디 알고리즘 (1~2를 반복)
1. 가방의 용량이 작은 것부터 채운다.
2. 가격이 높은 보석부터 담는다.
1. 가방의 용량이 작은 것부터 채운다.
- 입력받은 가방 정보를 sort(bag.begin(), bag.end())로 가방의 용량이 작은 순서로 정렬한다.
- for (int i = 0; i < k; i++) { ... } 로 가방의 용량이 작은 순서부터 가방 수 만큼 그리디 알고리즘을 수행한다.
- 위의 과정을 통해 가방의 용량이 작은 것부터 채워나간다.
- 무게가 무거워 용량이 작은 가방에 들어가지 못한 보석은 용량이 큰 가방에 들어갈 수 있다.
- 하지만 반대로 용량이 큰 가방에 들어가지 못한 보석은 작은 가방에 들어갈 수 없다.
- 따라서 가방의 용량이 작은 것부터 가방의 용량이 큰 것 순서대로 채워나가면 문제가 되지 않고 최선의 결과를 얻는다. 이를 바탕으로 그리디 알고리즘을 수행하면 올바른 결과를 얻을 수 있다.
2. 가격이 높은 보석부터 담는다.
- 보석을 무게 순서로 정렬한다.
- 우선순위 큐(Priority Queue)
- 우선순위 큐(Priority Queue) 선언. priority_queue<int> pQ; (이 우선순위 큐에는 보석의 가치를 담음)
- 담으려는 보석의 무게가 가방의 무게보다 작거나 같다면 현재 가방에 담을 수 있는 보석들을 pQ에 모두 담음. 이때 담을 수 있는 보석들의 가치를 담음.
- pQ에서 가장 높은 가치의 보석 하나를 answer에 더한다. (이 문제에서 " 가방에는 최대 한 개의 보석만 넣을 수 있다."라고 적혀 있다.)
주의할 점!!
정답으로 출력하는 ' 훔칠 수 있는 보석의 최대 가격 '인 answer의 자료형은
int answer이 아닌 long long answer 이어야 한다!!
int를 사용하면 오버플로우가발생하여 long long을 사용해야 한다.
정답 코드 - priority_queue
#include <iostream>
#include <vector>
#include <algorithm>
#include <queue>
using namespace std;
struct Spec {
int weight; int value;
};
bool Compare(Spec a, Spec b) {
return a.weight < b.weight; // 오름차순. 무게가 가벼운 순으로 정렬
}
int n, k; // n: 보석 수, k: 가방 수
vector<Spec> gem; // 무게, 가격
vector<int> bag; // 각 가방에 담을 수 있는 최대 무게
long long answer; // 훔칠 수 있는 보석의 최대 가격
int main() {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cin >> n >> k;
gem.resize(n);
for (int i = 0; i < n; i++) {
cin >> gem[i].weight >> gem[i].value;
}
bag.resize(k);
for (int i = 0; i < k; i++) {
cin >> bag[i];
}
sort(gem.begin(), gem.end(), Compare); // 오름차순. 무게가 가벼운 순으로 정렬
sort(bag.begin(), bag.end()); // 오름차순. 가벼운 가방 순서로 정렬
priority_queue<int> pQ; // 가격이 높은 순으로 보석을 저장할 우선순위 큐
int idx = 0; // 현재 보석의 인덱스
for (int i = 0; i < k; i++)
{
// 현재 가방에 담을 수 있는 보석들을 우선순위 큐에 넣음
while (idx < n && gem[idx].weight <= bag[i])
{
pQ.push(gem[idx].value);
idx++;
}
// 우선순위 큐에서 가장 가치가 높은 보석을 꺼냄 (가방에 넣음)
if (!pQ.empty()) {
answer += pQ.top();
pQ.pop();
}
}
cout << answer << "\n";
return 0;
}
정답 코드 - MultiSet
'⭐ 코딩테스트 > 백준' 카테고리의 다른 글
[백준 2166번 C/C++] 다각형의 면적 (0) | 2024.01.19 |
---|---|
[백준 2252번 C/C++] 줄 세우기 (0) | 2024.01.18 |
[백준 1005번 C/C++] ACM Craft (0) | 2024.01.16 |
[백준 2239번 C/C++] 스도쿠 (0) | 2024.01.15 |
[백준 2473번 C/C++] 세 용액 (1) | 2024.01.14 |
댓글
이 글 공유하기
다른 글
-
[백준 2166번 C/C++] 다각형의 면적
[백준 2166번 C/C++] 다각형의 면적
2024.01.19 -
[백준 2252번 C/C++] 줄 세우기
[백준 2252번 C/C++] 줄 세우기
2024.01.18 -
[백준 1005번 C/C++] ACM Craft
[백준 1005번 C/C++] ACM Craft
2024.01.16 -
[백준 2239번 C/C++] 스도쿠
[백준 2239번 C/C++] 스도쿠
2024.01.15