300x250

1. 제목

- 백준 15903 카드 합체 놀이

- BOJ 15903 카드 합체 놀이

 

문제 링크 : 15903번: 카드 합체 놀이 (acmicpc.net)

 

15903번: 카드 합체 놀이

첫 번째 줄에 카드의 개수를 나타내는 수 n(2 ≤ n ≤ 1,000)과 카드 합체를 몇 번 하는지를 나타내는 수 m(0 ≤ m ≤ 15×n)이 주어진다. 두 번째 줄에 맨 처음 카드의 상태를 나타내는 n개의 자연수 a1,

www.acmicpc.net


2. 풀이 과정

 

이 카드 합체를 총 m번 하면 놀이가 끝난다. m번의 합체를 모두 끝낸 뒤, n장의 카드에 쓰여있는 수를 모두 더한 값이 이 놀이의 점수가 된다. 이 점수를 가장 작게 만드는 것이 놀이의 목표이다.

 

이문제에서 핵심 문장이라고 생각합니다. N개의 카드들 중 2개를 선정해서 합체를 하면 2개의 카드가 모두 같은 숫자가 된다는 규칙이 있기 때문에 가장 작은 숫자의 카드끼리 합체를 하는 게 유리합니다. 그렇기에 이문제는 카드들을 오름차순으로 정렬하고 가장 작은 숫자의 카드 2장을  합치 고를 M번 반복하는 방법으로 풀었습니다. 정렬방법으로는 우선순위큐를 이용하여 큐에 넣을 때 카드들이 정렬되게 했습니다.

 

1. 우선순위큐에 카드를 넣는다.
2. 가장 작은 숫자의 카드 2장을 골라 우선순위큐에서 빼고 합친다음 다시 우선순위큐에 넣는다


3. 코드

// 1. 우선순위큐에 카드를 넣는다.
// 2. 가장 작은 숫자의 카드 2장을 골라 우선순위큐에서 빼고 합친다음 다시 우선순위큐에 넣는다

#include <iostream>
#include <queue>
#include <functional>

using namespace std;

int main()
{
    int n, m;
    priority_queue <long long, vector<long long>, greater<long long>> cards;

    cin >> n >> m;

    for (int i = 0; i < n; i++)
    {
        long long card;
        cin >> card;

        // 1. 우선순위큐에 카드를 넣는다.
        cards.push(card);
    }

    for (int i = 0; i < m; i++)
    {
        // 2. 가장 작은 숫자의 카드 2장을 골라 우선순위큐에서 빼고 합친다음 다시 우선순위큐에 넣는다
        long long card1 = cards.top();
        cards.pop();
        long long card2 = cards.top();
        cards.pop();

        long long mergeCard = card1 + card2;
        cards.push(mergeCard);
        cards.push(mergeCard);
    }

    long long result = 0;
    for (int i = 0; i < n; i++)
    {
        result += cards.top();
        cards.pop();
    }

    cout << result << endl;

    return 0;
}
300x250

'<C++ 백준 BOJ> > 그리디' 카테고리의 다른 글

[백준 BOJ1946] 신입 사원 (C++)  (0) 2023.07.09
[백준 BOJ13305] 주유소 (C++)  (0) 2023.07.02
[백준 BOJ1789] 수들의 합 (C++)  (0) 2023.07.02
[백준 BOJ1026] 보물 (C++)  (0) 2023.07.02
[백준 BOJ2217] 로프 (C++)  (0) 2023.07.02