최소비용 포장

사탕 공장에서는 요구에 따라 다양한 개수의 사탕을 담고 있는 포장을 하고 있다. 어느 날 갑자기 대형 이벤트가 생겨서 공장에 있는 모든 사탕들을 풀어서 하나로 포장 해야 한다.
 
A, B, C 3개의 사탕 포장이 있을 때 이 포장들을 한번에 하나로 합칠 수는 없고, 한번에 2개씩만 합칠 수 있다. 예를 들면 A와 B를 먼저 합친 후 C를 다시 합치거나 A와 C를 먼저 합치고 B를 합치기, 혹은 B와 C를 먼저 합치고 A를 합칠 수 있다.
 
사탕 포장을 풀었다가 다시 합치는 순서는 매우 중요한데, 그 이유는 그 순서에 따라 전체 비용이 달라지기 때문이다.
 
사탕 포장 A와 B에 각각 a개와 b개의 사탕이 들어있다고 할 때 이 둘을 합치는 비용은 a + b라고 한다. 그러므로 A와 B를 먼저 합치고 C를 합치는 경우 그 전체 비용은 a + b + a + b + c이며, B와 C를 먼저 합치고 A를 합치는 비용은 b + c + b + c + a 이므로 그 둘은 서로 같지 않을 수 있다.
 
예를 들어, 각각 2, 2, 5개가 포장되어 있다면 A(2)와 B(2)를 합치는 비용은 4. 합쳐진 것(4)과 C(5)를 합치는 비용은 9로 총 13이 최소비용이다.
 
현재 공장에 포장되어 있는 포장 개수 N과 각각 포장에 들어있는 사탕의 개수 ni가 주어질 때, 이들을 하나로 합치는데 들어가는 비용의 최소(C)를 구하라.

입력

첫 번째 줄에는 포장 개수 N(1<=N<=5000)이 주어진다.
두 번째 줄에는 포장에 들어있는 사탕의 개수 ni(1<=ni<=100)가 주어진다.

출력

최소 비용을 출력한다.

입력 예시

3
2 2 5

출력 예시

13

#include <stdio.h>
#define MAX 5003
int N;
int ni[MAX];
int tree[MAX];
int leaf = 0;

void push_heap(int n) {
 if (leaf == MAX) return;
 int me = ++leaf;
 tree[me] = n;
 int parent = me / 2;
 int tmp;

 while (parent > 0) {
  if (tree[parent] > tree[me]) {
   tmp = tree[me];
   tree[me] = tree[parent];
   tree[parent] = tmp;

   me = parent;
   parent = me / 2;
  }
  else break;
 }
}

int pop_heap() {
 if (leaf <= 0) return -1;
 int target = tree[1];
 int p,lc, rc,c;
 tree[1] = tree[leaf--];
 p = 1;
 lc = 2, rc = 3;
 while (lc <= leaf) {

  if (lc == leaf) c = lc;
  else {
   if (tree[lc] < tree[rc]) c = lc;
   else c = rc;
  }

  if (tree[p] > tree[c]) {
   int t = tree[p];
   tree[p] = tree[c];
   tree[c] = t;
   p = c;
   lc = p * 2;
   rc = p * 2 + 1;
  }
  else break;
 }

 return target;
}



void input_data() {
 scanf("%d", &N);
 for (int i = 1; i <= N; i++) {
  scanf("%d", &ni[i]);
  push_heap(ni[i]);
 }
}

int solve() {
 int sum = 0;
 
 for (int i = 1; i <= N-1; i++) {
  int t= pop_heap() + pop_heap();
  sum += t;
  push_heap(t);
 }
 return sum;
}

int main(void)

{
 // 여기서부터 작성
 input_data();
 printf("%d", solve());

 return 0;

}

댓글

이 블로그의 인기 게시물

어민

구슬집어넣기