본문 바로가기
알고리즘/BAEKJOON

BOJ 1715 : 카드 정렬하기

by 피로물든딸기 2021. 4. 9.
반응형

알고리즘 문제 전체 링크

 

www.acmicpc.net/problem/1715

 

 

카드 비교 횟수를 줄이기 위해서는 가장 작은 수의 두 카드를 비교해야한다.

그리고 카드를 합친다. (+ 횟수를 누적한다.)

그러면 다시 남은 카드(+ 합친카드 포함) 중에서 가장 작은 수의 두 카드를 비교해야한다.

 

따라서, 우선순위 큐를 이용한다.

가장 작은 두 카드는 두 번 pop하면 얻을 수 있고,

합친 카드를 우선순위 큐에 넣어도 우선순위 큐를 두 번 pop하면 가장 작은 두 카드를 구할 수 있다.

#include <stdio.h>

int N;

int heap[100100];
int hn;

int pop(int* heap, int& hn)
{
	int tmp, ret;

	ret = heap[1];
	heap[1] = heap[hn];
	heap[hn--] = 0x7fff0000;

	for (int i = 1; i * 2 <= hn;)
	{
		if (heap[i] < heap[i * 2] && heap[i] < heap[i * 2 + 1]) break;
		else if (heap[i * 2] < heap[i * 2 + 1])
		{
			tmp = heap[i * 2];
			heap[i * 2] = heap[i];
			heap[i] = tmp;

			i = i * 2;
		}
		else
		{
			tmp = heap[i * 2 + 1];
			heap[i * 2 + 1] = heap[i];
			heap[i] = tmp;

			i = i * 2 + 1;
		}
	}

	return ret;
}

void push(int* heap, int& hn, int x)
{
	int tmp;

	heap[++hn] = x;
	for (int i = hn; i > 1; i /= 2)
	{
		if (heap[i / 2] <= heap[i]) break;

		tmp = heap[i / 2];
		heap[i / 2] = heap[i];
		heap[i] = tmp;
	}
}

int main()
{
	int total, sum;

	scanf("%d", &N);
	for (int i = 0; i < N; i++)
	{
		int tmp;
		scanf("%d", &tmp);

		push(heap, hn, tmp); /* 카드를 모두 넣는다. */
	}

	total = sum = 0;
	for (int i = 0; i < N - 1;i++)
	{
		sum = 0;
		sum += pop(heap, hn); /* 가장 작은 카드 2개를 뽑는다. */
		sum += pop(heap, hn); 

		total += sum; /* 횟수를 누적한다. */
		push(heap, hn, sum); /* 합친 카드를 다시 heap에 넣는다. */
	}

	printf("%d\n", total);

	return 0;
}
반응형

'알고리즘 > BAEKJOON' 카테고리의 다른 글

BOJ 2630 : 색종이 만들기  (0) 2021.04.25
BOJ 1080 : 행렬  (0) 2021.04.10
BOJ 1644 : 소수의 연속합  (0) 2021.04.02
BOJ 2467, 2470 : 두 용액  (0) 2021.03.29
BOJ 10830 : 행렬 제곱  (0) 2021.03.25

댓글