1715번: 카드 정렬하기
정렬된 두 묶음의 숫자 카드가 있다고 하자. 각 묶음의 카드의 수를 A, B라 하면 보통 두 묶음을 합쳐서 하나로 만드는 데에는 A+B 번의 비교를 해야 한다. 이를테면, 20장의 숫자 카드 묶음과 30장
www.acmicpc.net
문제 분석
문제에서는 '규칙'과 함께, 카드를 한묶음으로 만드는 '최소 비교 횟수'를 구하도록 한다.
💡규칙💡
- 여러 개의 카드 묶음을 뭉치기 위해서는, 두 묶음씩 뭉칠 수 있다.
- N개의 묶음이 시작이고, 이 중 2개의 묶음을 하나로 뭉쳤다면, 다시 N - 1개의 묶음에서 2개를 골라 뭉친다.
- 총 1개의 묶음이 완성될 때 까지 이 과정을 반복한다.
문제에서 말한 과정을 짧게 3가지 단계로 표현하였다.
결국 두 묶음씩 조합할 때의 조건이 중요한 거 같은데... 어떻게 할까?
문제 풀이
문제 해결방법을 구하는 것은 쉽다!
Example
가정 : 카드묶음 10 20 70 25 이 있다.
1. 먼저 입력받은 카드묶음을 정렬한다.
-> 10 20 25 70
2. 4개의 카드묶음에서 가장 작은 2개의 묶음을 선정하고 합친다.
-> 10 + 20 = 30
3. 하나로 만든 묶음을 다시 카드묶음의 뭉치에 넣는다. (이 때, 정렬이 다시 되어야한다.)
-> 25 30 70
4. 다시 2, 3과정을 반복한다.
-> 25 + 30 = 55
-> 55, 70
-> 55 + 70 = 125
결국 N개의 카드묶음에서,
(1) 카드의 갯수가 가장 적은 2개를 하나의 묶음으로 만들고,
(2) 이 카드 묶음을 다시 다른 카드 묶음과 비교하여, (이 때, 카드묶음의 총 갯수는 N - 1)
(1) 가장 카드의 갯수가 적은 2개를 하나의 묶음으로 만든다.
.
.
.
이 2개의 과정만을 반복하면 된다!
이제 방법 자체는 생각했으니, 구현을 해야하는데...
필자는 구현과정이 훨씬 어려웠다.
위 2개의 과정을 거치기 위해서는
내가 처음에 뽑은 2개의 카드묶음을 하나로 묶은 뒤, 다시 카드묶음의 배열에 넣었을 때, 정렬된 형태로 존재해야했다.
sort함수를 계속해서 사용하기에는 시간이 초과될것 같았다...
.......
💡우선순위 큐!💡
만약 정렬을 계속해서 해야하는 배열이 필요한 문제라면, 무조건 우선순위 큐를 사용하면 된다!
이 때, 우선순위 큐의 기본 형태는 내림차순이기에, greater<int>를 활용하여 오름차순으로 바꿔서 정렬시켜두면 완성이다!
ex)
'que'라는 우선순위 큐가 선언되어있고, {10 40 30 20} 순으로 'que'에 push된다면
자동으로 que = {40 30 20 10} 형태로 정렬될 것이다.
C++ 풀이
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int N;
cin >> N;
priority_queue<int, vector<int>, greater<int>> q; // 우선순위 큐를 오름차순으로 정렬
for (int i = 0; i < N; i++) {
int x;
cin >> x;
q.push(x);
}
int sum = 0;
while (q.size() != 1) {
int x = q.top();
q.pop();
int y = q.top();
q.pop();
sum += (x + y);
q.push(x + y);
}
cout << sum;
return 0;
}
코드 리뷰는 언제나 환영입니다!
'알고리즘' 카테고리의 다른 글
백준 10026번 적록색약(c++) (0) | 2024.01.25 |
---|---|
백준 2195번 문자열 복사(C++) (1) | 2024.01.24 |
백준 1149번 RGB거리 (C++) (1) | 2024.01.02 |
백준 18870번 좌표 압축(C++) (lower_bound) (1) | 2023.12.31 |
백준 13335번 트럭(c++) (2) | 2023.12.30 |