Problem Solving/랜덤 마라톤

Baekjoon 15903: 카드 합체 놀이

wrathlion 2024. 9. 2. 23:09

문제 설명

  • 문제 링크
  • Algorithm: Greedy, Priority Queue
  • 난이도: Silver 1 ('24. 9. 2.)
  • 출처: 랜덤 마라톤 코스 12

풀이

  • 가정: 전체 카드의 합을 $S$라 하자
  • 추론: 한 번의 과정이 끝나면 $S - x - y + (x + y) + (x + y) = S + (x + y)$ 이다.
  • 결론: $m$번의 과정을 끝낸 뒤 $S$가 가장 작아지려면 한 번의 과정 때 선택하는 $(x + y)$가 가장 작아야한다.
    • 즉, 한 번의 과정에서 가장 작은 x, y를 선택한 뒤 더해준다!
    • 매 과정마다 값이 바뀌고, 바뀐 배열에서 2개의 작은 값들을 찾아야 하니 우선순위 큐로 과정을 구현한다.

코드

// Baekjoon15903.cpp
#include <iostream>

#include <queue>
#include <vector>

using namespace std;

using ll = long long;

struct compare {
    bool operator()(ll a, ll b) {
        return a > b;
    }
};

int main(void) {
    ios_base::sync_with_stdio(false);
    cin.tie(0);

    int n, m;
    cin >> n >> m;

    ll sum = 0LL;
    priority_queue<ll, vector<ll>, compare> pq;
    for (int i = 0; i < n; i++) {
        ll num;
        cin >> num;

        sum += num;

        pq.push(num);
    }

    while (m--) {
        ll small1 = pq.top(); pq.pop();
        ll small2 = pq.top(); pq.pop();

        ll twoSum = small1 + small2;

        sum += twoSum;

        pq.push(twoSum);
        pq.push(twoSum); 
    }

    cout << sum << '\n';

    return 0;
}

잡담

  • 사실 저렇게 수식 쓰고 그랬지만 생각할 때는 작은거 2개 선택하면 무조건 될 듯이라 생각했다!
  • 옛날에 풀었지만 요즘 다른 일들이 많다보니 이제 올린다 ㅎ 앞으로 밀린 문제가 많으니 부지런히 올려보겠다!