백준 1202 보석 도둑 [c++]

c++

중간에 자바로 풀고싶은 마음이 머리끝까지 차올랐지만, c++로 해결했다 후.

문제 분석

  • 도둑이 보석점을 턴다.
  • N개의 보석이 주어진다.
    • 보석은 무게 M과 가치 V로 이루어져 있다.
  • K개의 가방이 주어진다.
    • 도둑은 가방에 한 개의 보석만 넣을 수 있고,
    • 각 가방별로 최대 무게가 정해져 있다.
  • 도둑이 가져갈 수 있는 최대 보석의 가치는?

입력조건

보석의 수 N 가방의 수 K
N줄에 걸쳐 {
	보석 무게 M 보석 가치 V
}
K줄에 걸쳐 {
	가방 최대 무게 C
}

풀이과정

  • 이 문제의 핵심은 정렬이라고 생각한다.

  • 받은 보석 배열과, 가방 배열을 모두 오름차순으로 정렬한다.

  • 이 상태에서 제일 가져갈 수 있는 무게가 작은 가방부터, 하나씩 올라가며 각 가방에 넣을 보석을 결정한다.

  • while문으로 모든 가방을 채우기 전까지 반복한다.

  • while문 바깥에 priority queue를 하나 선언한다.

    • 이 queue에는 내가 가방에 넣을 수 있는 가치들이 들어간다.
    • while문 밖에 이를 정의하는 이유는, pq가 초기화되면 안돼기 때문이다.
    • pq에는 항상 지금까지 가능한 모든 보석의 가치가 들어가 있어야 한다.
  • while문 안에 다시 while문을 하나 만들어서,
    현재 가방이 버티는 무게보다 보석이 작은 모든 보석을 queue에 넣는 연산을 실행.

  • 위의 안쪽 while문을 빠져나오면, 지금 위치의 가방에 넣을 수 있는 보석의 가치들이 queue에 들어있고, 심지어 내림차순으로 정렬되어 있다.

  • 이 큐에서 하나를 pop한 뒤, 다음 반복을 실행한다.

  • 예외처리도 잊지 말 것!

전체 코드

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


using namespace std;

struct gem {
    int size;
    long long value;
};

bool comparegem(gem a, gem b) {
    return a.size < b.size;
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);

    // N개의 보석, K개의 가방
    int N, K;
    cin >> N >> K;

    // N 개의 보석 크기 나열
    gem gems[N];
    for(int i = 0; i < N; i++)
        cin >> gems[i].size >> gems[i].value;

    // K 개의 가방 크기 나열.
    int bags[K];
    for(int i = 0; i < K; i++) 
        cin >> bags[i];
    // 입력 끝.

    // 정렬.(all 오름차순)
    sort(gems, gems + N, comparegem);
    sort(bags, bags + K);

    int gemidx = 0;
    int bagidx = 0;

    long long ans = 0;
    priority_queue<long long> pq;
    
    // K번째 가방까지 다 넣을 때 까지 반복.
    while(bagidx < K) {

        // 가능한 모든 가치를 queue에 넣음.
        while(gemidx < N && gems[gemidx].size <= bags[bagidx]){
            pq.push(gems[gemidx].value);
            gemidx++;
        }
        if(!pq.empty()) {
            ans += pq.top();
            pq.pop();
        }
        bagidx++;
    }
    
    cout << ans << endl;
}