https://www.acmicpc.net/problem/1715
1715번: 카드 정렬하기
정렬된 두 묶음의 숫자 카드가 있다고 하자. 각 묶음의 카드의 수를 A, B라 하면 보통 두 묶음을 합쳐서 하나로 만드는 데에는 A+B 번의 비교를 해야 한다. 이를테면, 20장의 숫자 카드 묶음과 30장
www.acmicpc.net

난이도: solved.ac 골드 4
처음에 문제 풀이를 시도했을 때
이게 골드 4? 너무 쉬운데? ㅋㅋㅋㅋㅋㅋ 하고 답안을 제출했지만
틀렸습니다
....?
'어디가 틀린 거지?' 하고 의아했던 문제다
이 문제에서 주의할 점 두 가지가 있다
1. 비교할 카드 묶음의 개수가 남아있는 카드 묶음 중 최소가 되어야 하는 점
2. N = 1일 때는 비교할 대상이 없으므로 0이 출력되어야 한다는 점
1번의 경우를 예를 들어 설명하겠다
10개 짜리로 된 5개의 카드 묶음이 있다고 할 때(10, 10, 10, 10, 10)
10 + 10 = 20
20 + 10 = 30
30 + 10 = 40
40 + 10 = 50
으로 20 + 30 + 40 + 50 = 140이 아니라

처럼 묶여서
10 + 10 = 20
10 + 10 = 20
10 + 20 = 30
20 + 30 = 50
으로 20 + 20 + 30 + 50 = 120이 되어야 한다
구현은 우선순위 큐를 이용하였다
자료구조에서 배운 우선순위 큐를 복습하기 위해
책 '윤성우의 열혈 자료구조'에 나온 코드를 참고하면서 풀었다
#define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #define HEAP_LEN 100001 #define TRUE 1 #define FALSE 0 typedef int PriorityComp (int data1, int data2); // 우선 순위를 정해줄 함수 typedef struct _heap { PriorityComp* comp; int numOfData; int heapArr[HEAP_LEN]; } Heap; int GetParentIDX(int idx); int GetLChildIDX(int idx); int GetRChildIDX(int idx); int GetHighPriChildIDX(Heap* ph, int idx); int numPriorityComp(int a, int b); void PQueueInit(Heap* ph, PriorityComp pc); int PQIsEmpty(Heap* ph); void PEnqueue(Heap* ph, int num); int PDequeue(Heap* ph); int main() { int N; Heap pq; scanf("%d", &N); PQueueInit(&pq, numPriorityComp); int num; for (int i = 0; i < N; i++) { scanf("%d", &num); PEnqueue(&pq, num); } int a, b; int total = 0; while(!PQIsEmpty(&pq)) { a = PDequeue(&pq); if (PQIsEmpty(&pq)) break; b = PDequeue(&pq); total += a + b; PEnqueue(&pq, a + b); } printf("%d", total); return 0; } int GetParentIDX(int idx) { return idx / 2; } int GetLChildIDX(int idx) { return idx * 2; } int GetRChildIDX(int idx) { return idx * 2 + 1; } int GetHighPriChildIDX(Heap* ph, int idx) { if (GetLChildIDX(idx) > ph->numOfData) // child가 없을 때 return 0; else if (GetLChildIDX(idx) == ph->numOfData) // child가 하나 있을 때(child는 왼쪽부터 채워지므로) return GetLChildIDX(idx); // 그 하나 있는 child의 index를 return else { // child가 2개 있을 때 if (ph->comp(ph->heapArr[GetLChildIDX(idx)], ph->heapArr[GetRChildIDX(idx)]) < 0) return GetLChildIDX(idx); // left child가 right child보다 작을 때 else return GetRChildIDX(idx); // left child가 right child보다 크거나 같을 때 } } int numPriorityComp(int a, int b) { /* a가 b보다 크면 양수 a와 b가 같으면 0 a가 b보다 작으면 음수 출력 */ return a - b; } void PQueueInit(Heap* ph, PriorityComp pc) { ph->numOfData = 0; ph->comp = pc; } int PQIsEmpty(Heap* ph) { if (ph->numOfData == 0) return TRUE; else return FALSE; } void PEnqueue(Heap* ph, int num) { int idx = ph->numOfData + 1; while (idx != 1) { if (ph->comp(num, ph->heapArr[GetParentIDX(idx)]) < 0) { ph->heapArr[idx] = ph->heapArr[GetParentIDX(idx)]; idx = GetParentIDX(idx); } else break; } ph->heapArr[idx] = num; (ph->numOfData)++; } int PDequeue(Heap* ph) { int retnum = ph->heapArr[1]; int lastElem = ph->heapArr[ph->numOfData]; int parentIdx = 1; int childIdx; while (childIdx = GetHighPriChildIDX(ph, parentIdx)) { if (ph->comp(lastElem, ph->heapArr[childIdx]) <= 0) break; ph->heapArr[parentIdx] = ph->heapArr[childIdx]; parentIdx = childIdx; } ph->heapArr[parentIdx] = lastElem; (ph->numOfData)--; return retnum; }