ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [백준] 1202번 보석 도둑
    문제 풀이 2020. 8. 2. 18:21

    1202 보석도둑


    문제


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

    상덕이가 털 보석점에는 보석이 총 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)

    모든 숫자는 양의 정수이다.


    출력


    첫째 줄에 상덕이가 훔칠 수 있는 보석 가격의 합의 최댓값을 출력한다.



    풀이)

    greedy 문제이다.

    "무게가 낮은 가방부터 최대한 가격 높은 보석을 넣는다" 가 핵심 point다.


    과정

    1. 보석을 무게순으로 정렬해놓는다. (무게 낮은 순 -> 무게 높은 순)

    2. 가방을 무게순으로 정렬해놓는다. (무게 낮은 순 -> 무게 높은 순)

    3. 가방 개수만큼 반복문을 돌린다.

      3.1 i번째 가방 무게보다 가벼운 보석들의 가격을 모두 PQ에 넣는다.

      3.2 PQ의 top 값을 결과값에 더한다.

           (PQ는 내림차순으로 가격이 높은 순에서 -> 낮은 순으로 정렬해준다. 

      따라서 top값을 더한다면 그것은 곧 현재 가방무게보다 가벼우며, 

        가격이 가장 높은 보석을 그 가방에 넣어주는 것이다.)


    주의사항

    1. 결과값의 자료형을 int로 선언하면 안된다.

       가격의 최대값 300,000 * 가방의 개수 1,000,000 = 300,000,000,000

       *int형의 범위를 넘어갈 수 있다.*

       (이를 간과해 여러번 틀렸다.)


    2. 보석을 가격(높->낮), 무게(낮->높) 순으로 정렬하고

        PQ가 아닌 이중 포문으로 돌리면 시간초과가 난다. 


    시간초과 코드.

    bool cmp(const pair<int, int> &a, const pair<int, int> &b) {

    if (a.first == b.first) return a.second < b.second;

    return a.first > b.first;

    }

    ...

          sort(jew.begin(), jew.end(), cmp);

    ...

    for (int i = 0; i < K; i++) {

    for (int j = 0; j < jew.size(); j++) {

    if (jew[j].first == -1) continue;

    if (jew[j].second <= weight[i]) {

    result += jew[j].first;

    jew[j].first = -1;

    break;

    }

    }

    }


    코드)


    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
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    #include <stdio.h>
    #include <algorithm>
    #include <vector>
    #include <queue>
    using namespace std;
     
    int N, K, M, V, C;
    vector<int> weight;
    vector<pair<intint>> jew;
     
    int main() {
        scanf("%d %d"&N, &K);
        for (int i = 0; i < N; i++) {
            scanf("%d %d"&M, &V);
            jew.push_back({ M,V });
        }
     
        for (int i = 0; i < K; i++) {
            scanf("%d"&C);
            weight.push_back(C);
        }
        //보석 : 무게(낮->높) 순
        sort(jew.begin(), jew.end());
        //가방 : 무게(낮->높) 순
        sort(weight.begin(), weight.end());
        long long result = 0//300,000 * 1,000,000
        int i = 0, j = 0;
        priority_queue <int> qu; //priority_queue는 내림차순, 가격순으로
     
        //무게가 낮은 가방부터 최대한 가격이 높은 보석을 넣음
        for (int i = 0; i < K; i++) {
            while (j < N) {
                if (jew[j].first <= weight[i]) {
                    qu.push(jew[j].second);
                    j++;
                }
                else break;
            }
            if (!qu.empty()) {
                result += qu.top();
                qu.pop();
            }
        }
     
        printf("%lld\n", result);
        return 0;
    }
    cs

       

    '문제 풀이' 카테고리의 다른 글

    [백준] 3197번 백조의 호수  (0) 2020.08.04
    [백준] 2942번 퍼거슨과 사과  (0) 2020.08.03
    [백준] 10986번 나머지 합  (0) 2020.08.01
    [백준] 17780번 새로운 게임  (0) 2020.07.31
    [백준] 6087번 레이저 통신  (0) 2020.07.30

    댓글

Designed by Tistory.