일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 31 |
- 구슬탈출
- stl
- 풀이
- 백준 2133
- 1796
- 데이터 링크 계층
- mediastream
- 구현
- dp
- 페이지교체알고리즘
- LOLIN D32
- 9996
- 3XN 타일링
- TDD란?
- WebRTC란
- 적두트리
- 백준
- 2623
- REACT
- 테스트주도개발
- TDD
- 자료구조
- tfjs
- Vite 사용 이유
- RBT
- c++
- 13459
- ESP32
- OpenVidu
- 메모리계층
- Today
- Total
그냥 블로그
[백준/C++] 보석 도둑 본문
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개를 상덕이의 가방(무게가 정해져 있는) K개에 넣었을 때 최대 가격을 구하기.
[풀이 과정]
우선, 이 문제가 가방의 무게, 보석의 무게와 가치 이렇게 입력을 받고
가방 무게에 따라 넣을 수 있는게 다르기 때문에 정렬을 해야겠다고 생각했다.
일단, 처음에는 문제만 대충 보고 냅색 알고리즘인 줄 알았다. 근데 좀 생각해보면 안된다는 걸 알 수 있다.
=> DP로 풀기엔 메모리공간이나 시간 제약에 걸린다.
완탐으로 풀게 될 경우에는 N과 K의 최대가 3만이기 때문에 30만*30만 해서 안된다는 것도 알 수 있음. (1초 초과)
그 다음으로, 가방을 하나씩 돌면서넣을 수 있는 보석을 모두 하나씩 대입해본다 했을 때..
가방의 무게가 늘어날 수록 확인해봐야 하는 보석의 개수가 늘어나는데 이걸 매번 반복문으로 돌려주는게 완전 탐색이고
이 경우 시간이 안되기 때문에 한번에 할 수 있는 방법을 생각해야 했다.
=> priority_queue를 사용하면 가능한 무게 중 가치가 제일 높은 보석을 골라내기 쉬울 거라 생각..
1. 정렬을 해준다 ( 오름차순 )
vector<pair<int, int>> jewelry; // 무게, 가치.
2. pq를 만들고, pq에 내 무게 이하의 보석들을 넣어준다. => priority_queue<int> pq
=> 무게는 낮기만 하면 상관 없기 때문에 가치만 넣어준다.
// i는 가방
for(int i = 0; i < 가방 개수; i++){
while(남아있는 보석이 있으면){
if(보석의 무게가 현재 가방(i)보다 높으면) break;
else pq에 보석의 가치를 넣는다.
}
// 위의 while문이 종료되었을 때,
if(pq에 보석이 존재)
정답에 가장 높은 가치의 보석을 꺼내어 넣는다
}
[코드]
#include<iostream>
#include<vector>
#include<queue>
#include<algorithm>
using namespace std;
int N, K; // 보석 개수, 가방 개수
vector<pair<int, int>> jewelry;//보석 무게, 가치
vector<int> bag;
int main() {
cin >> N >> K;
for (int i = 0; i < N; i++) {
int M, V; // 무게, 가격
cin >> M >> V;
jewelry.push_back({ M,V });
}
for (int i = 0; i < K; i++) {
int C; // 가방 무게
cin >> C;
bag.push_back(C);
}
sort(jewelry.begin(), jewelry.end());
sort(bag.begin(), bag.end());
priority_queue<int> pq;
int num = 0;
long long sum = 0;
for (int i = 0; i < K; i++) {
while (num < jewelry.size()) {
if (jewelry[num].first > bag[i]) break;
pq.push(jewelry[num].second);
num++;
}
if (!pq.empty()) {
sum += pq.top();
pq.pop();
}
}
cout << sum;
}
[고찰]
다 괜찮았는데 2%? 3%? 에서 틀렸습니다...
정답을 int 형으로 썼을 때, 정답이 범위를 넘어버리는 상황이 발생했다.
최대 무게가 1억임..;; 1억에 30만 곱한다고 하면 int 자료형의 범위를 넘어버리는 것. long long을 사용하니까 되긴 했다.
여지껏 int 자료형 범위를 한번도 고려해가면서 문제를 푼 적이 없는데 한 20억쯤 된다는 것...
'C++ > 백준' 카테고리의 다른 글
[C++/백준] 1647 도시분할계획 (1) | 2024.01.07 |
---|---|
[C++/백준] 2143 두 배열의 합 (1) | 2023.12.29 |
[백준/C++] 14499. 주사위 굴리기 (1) | 2023.12.08 |
[백준/C++] 1005 ACM Craft (2) | 2023.12.03 |
[백준/C++] 27172 수 나누기 게임 (0) | 2023.11.26 |