[BOJ] C++ 15903 카드 합체 놀이 - 우선순위 큐와 오버플로우 조심하기
2023. 8. 6. 16:13ㆍ알고리즘/문제풀이
예제 1
3 1
3 2 6
answer : 16
예제 2
4 2
4 2 3 1
answer : 19
n개의 카드에 대해 어떤 두 카드의 숫자를 그 두 카드의 합으로 바꾸는 것을 m번 진행한 뒤 n개의 카드의 숫자 합이 최소가 되게 하는 문제이다. 먼저 그리디 하게 매 턴마다 가장 작은 숫자 두 개를 고르면 된다고 생각했다.
매 턴마다 그리디 하게 숫자를 고르는 것까지는 문제가 없어 보였고, 구현 부분은 우선순위 큐를 이용해 간단히 우선순위를 내림차순으로 하고, pop 두 번 후 두 숫자를 더한 값을 push 두 번 하는 식으로 구현했다.
여기까지는 쉬웠지만 주의할 점이 하나 있었다. n개의 카드가 최대 1,000개이고 15 * n번의 턴이 진행되며 각 카드의 숫자는 최대 1,000,000여서 int 자료형으로 구현하게 되면 오버플로우가 발생한다. 따라서 모든 자료형을 long long으로 바꿔주었다. 자료형을 long long으로 바꿀 때 연산 과정에서 일부 int가 섞여있으면 계산에 오류가 발생할 수 있으므로 콤팩트하게 다 바꿔주자.
/** 우선순위 큐 15903 카드 합체 놀이 **/
#include <iostream>
#include <vector>
#include <algorithm>
#include <queue>
using namespace std;
int main()
{
ios_base::sync_with_stdio(0);
cin.tie(0);
int n, m;
cin >> n >> m;
priority_queue<long long, vector<long long>, greater<long long>> cards;
long long sum = 0;
for (int i = 0; i < n; i++)
{
long long temp;
cin >> temp;
cards.push(temp);
sum += temp;
}
for (int i = 0; i < m; i++)
{
long long a = cards.top();
cards.pop();
long long b = cards.top();
cards.pop();
// a, b에 각각 우선순위 큐의 가장 작은 값 2개 저장
sum += a + b;
cards.push(a + b);
cards.push(a + b);
}
cout << sum << "\n";
}
'알고리즘 > 문제풀이' 카테고리의 다른 글
[BOJ] C++ 1744 수 묶기 - 조건에 따라 분류하며 정렬하기 (0) | 2023.08.09 |
---|---|
[문제풀이] int, long long 오버플로우, 시간초과 관련 미세 팁 (0) | 2023.08.06 |
[BOJ] C++ 2470 두 용액 - 투 포인터, 정렬 (0) | 2023.08.05 |
[BOJ] C++ 7795 먹을 것인가 먹힐 것인가 - 투 포인터, 정렬 (0) | 2023.08.02 |
[BOJ] C++ 24480 알고리즘 수업 - 깊이 우선 탐색 2 - DFS, 정렬 (0) | 2023.08.02 |