Кожного разу слід складати два найменших числа. Таким чином, сумарна вартість складання всіх чисел буде мінімальною. Оскільки числа можуть повторюватися, їх зручно зберігати в мультимножині.
Приклад
Для мінімізації вартості складання будемо складати числа в такому порядку:
Складаємо і , отримаємо . Вартість складання .
Складаємо і , отримаємо . Вартість складання .
Складаємо і , отримаємо . Вартість складання .
Загальна вартість складання дорівнює 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)