728x90
728x90
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;
}
반응형