Додати всі#1228

Додати всі (Розбір)

Кожного разу слід складати два найменших числа. Таким чином, сумарна вартість складання всіх чисел буде мінімальною. Оскільки числа можуть повторюватися, їх зручно зберігати в мультимножині.

Приклад

Для мінімізації вартості складання будемо складати числа в такому порядку:

  1. Складаємо і , отримаємо . Вартість складання .

  2. Складаємо і , отримаємо . Вартість складання .

  3. Складаємо і , отримаємо . Вартість складання .

Загальна вартість складання дорівнює 3 + 6 + 10 = 19.

Реалізація алгоритму

Вхідні числа зберігаємо в мультимножині (числа можуть повторюватися). Два найменших числа завжди розташовані на початку мультимножини.

multiset<long long> s;

Читаємо кількість чисел .

scanf("%lld",&n);

Читаємо послідовність доданків і додаємо їх в мультимножину .

for (i = 0; i < n; i++)
{
  scanf("%lld",&x);
  s.insert(x);
}

У змінній обчислюємо вартість складання всіх чисел.

res = 0;

Поки в мультимножині більше одного числа, дістаємо і складаємо два його найменших елементи і додаємо їхню суму назад в . Вартість складання чисел і дорівнює a + b, і вона додається до .

while (s.size() > 1)
{
  a = *s.begin(); s.erase(s.begin());
  b = *s.begin(); s.erase(s.begin());
  s.insert(a + b);
  res += a + b;
}

Коли в мультимножині залишається тільки одне число, виводимо відповідь — значення змінної .

printf("%lld\n",res);

Реалізація за допомогою черги з пріоритетами

Оголосимо чергу з пріоритетами , на початку якої завжди знаходиться найменший елемент.

priority_queue<long long, vector<long long>, greater<long long> > pq;

Читаємо кількість чисел .

scanf("%lld",&n);

Читаємо послідовність доданків і додаємо їх в чергу з пріоритетами .

scanf("%lld",&n);
for (i = 0; i < n; i++)
{
  scanf("%lld",&x);
  pq.push(x);
}

У змінній обчислюємо вартість складання всіх чисел.

res = 0;

Поки в черзі більше одного числа, дістаємо і складаємо два його найменших елементи і додаємо їхню суму назад в . Вартість складання чисел і дорівнює a + b, і вона додається до .

while (pq.size() > 1)
{
  a = pq.top(); pq.pop();
  b = pq.top(); pq.pop();
  pq.push(a + b);
  res += a + b;
}

Коли в черзі залишається тільки одне число, виводимо відповідь — значення змінної .

printf("%lld\n",res);

Java реалізація

import java.util.*;

public class Main
{
  public static void main(String[] args)
  {
    Scanner con = new Scanner(System.in);
    int n = con.nextInt();
    PriorityQueue<Long> pq = new PriorityQueue<Long>();
    for(int i = 0; i < n; i++)
    {
      long val = con.nextLong();
      pq.add(new Long(val));
    }
    long Result = 0;
    while(pq.size() > 1)
    {
      long a = pq.poll();
      long b = pq.poll();
      pq.add(a + b);
      Result += a + b;
    }
    System.out.println(Result);    
  }
}

Python реалізація

Оголосимо чергу з пріоритетами , на початку якої завжди знаходиться найменший елемент.

from queue import PriorityQueue
q = PriorityQueue()

Читаємо вхідні дані.

n = int(input())
lst = map(int,input().split())

Додамо доданки в чергу .

for x in lst:
  q.put(x)

У змінній обчислюємо вартість складання всіх чисел.

res = 0

Поки в черзі більше одного числа, дістаємо і складаємо два його найменших елементи і додаємо їхню суму назад в . Вартість складання чисел і дорівнює a + b, і вона додається до .

while q.qsize() > 1:
  a = q.get()
  b = q.get()
  q.put(a + b)
  res += a + b

Коли в черзі залишається тільки одне число, виводимо відповідь — значення змінної .

print(res)