티스토리 뷰
보석 도둑이 보석 가게에서 훔칠 수 있는 보석들의 최대 가격을 구하는 문제
문제의 조건
상덕이가 털 보석점에는 보석이 총 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)
모든 숫자는 양의 정수이다.
출력
첫째 줄에 상덕이가 훔칠 수 있는 보석 가격의 합의 최댓값을 출력한다.
풀이 과정
우선순위 큐를 만들어서 보석 가격을 비싼 순서대로 정렬한 뒤 가방에 넣을 수 있는 무게를 비교해보며 합계를 구하면 될 것 이라 생각했는데 처음에는 가방 무게 배열을 벡터로 썼다가 보석을 넣을 수 있는 가방을 탐색하는 과정에서 시간 초과가 나서... 가방 무게 배열을 multiset으로 바꾸고 통과했습니다.
* multiset : set과 같은데 중복 원소를 허용하는 set
1. key: 가격 value: 무게 pair 구조체를 저장하는 우선순위 큐를 만들어서 가격이 비싼 순서대로 정렬되도록 한다.
2. 가방 무게를 입력받는 배열을 multiset으로 만든다. 가방 검색 시 효율을 높이면서 무게가 같은 가방이 여러 개 있을 수도 있기 때문에 multiset 사용.
3. 보석 큐가 비기 전 까지나 가방 배열이 비기 전 까지 top에 있는 보석의 무게보다 같거나 큰 가방이 가방 배열에서 lower_bound로 찾아지면 합계에 더하고 가방 배열에서 삭제한다. 이 때 std::lower_bound는 set.lower_bound보다 속도가 느려서 시간초과가 나니 꼭 set의 멤버함수로 포함되어 있는 lower_bound를 사용해야 한다.
코드
#include <iostream>
#include <vector>
#include <queue>
#include <set>
using namespace std;
int main()
{
int N, K;
cin >> N >> K;
priority_queue<pair<int, int>> gems;
for (int i = 0; N > i; i++)
{
int weight, price;
cin >> weight >> price;
gems.emplace(make_pair(price, weight)); //key: 가격 value: 무게
}
multiset<int> bags;
for (int i = 0; K > i; i++)
{
int weight;
cin >> weight;
bags.insert(weight);
}
long long answer = 0; //오버 플로우 방지용
while (!bags.empty() && !gems.empty())
{
auto gem = gems.top();
gems.pop();
//현재 가장 비싼 보석을 담을 수 있는 가방이 있으면 합계에 보석 가격을 더하고 해당 가방 삭제
//lower_bound: 배열에서 인자값보다 같거나 큰 첫번째 원소를 찾아주는 함수
auto it = bags.lower_bound(gem.second);
if (bags.end() != it)
{
answer += gem.first;
bags.erase(it);
}
}
cout << answer;
return 0;
}
'알고리즘 문제 풀이 > Greedy' 카테고리의 다른 글
[C++] 백준 온라인 저지 2437번 저울 풀이 (0) | 2021.11.12 |
---|---|
[C++] 백준 온라인 저지 1080번 행렬 풀이 (0) | 2021.11.11 |
[C++] 백준 온라인 저지 16953번 A -> B 풀이 (0) | 2021.11.08 |
[C++] 백준 온라인 저지 1744번 수 묶기 풀이 (0) | 2021.11.07 |
[C++] 백준 온라인 저지 1439번 뒤집기 풀이 (0) | 2021.11.06 |
- Total
- Today
- Yesterday
- dp
- 기초
- 캐나다
- 하드웨어
- 컴퓨터공부
- 해커랭크
- 프로그래머스
- c++
- hackerrank
- 너비우선탐색
- 알고리즘
- c언어
- 영어공부
- BFS
- 그리디
- 컴퓨터사이언스
- 백준
- C언어기초
- 깊이우선탐색
- 다이나믹프로그래밍
- 캐나다생활
- greedy
- DFS
- 아이패드
- 코딩공부
- 문제풀이
- 애플
- 프로그래밍
- 컴퓨터
- 스위프트플레이그라운드
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |