Hər dəfə iki ən kiçik ədədi toplamaq lazımdır. Bu yolla bütün ədədlərinin toplanmasının ümumi dəyəri minimal olacaq. Ədədlər təkrarlana biləcəyi üçün onları çoxüzvlükdə saxlamaq əlverişlidir.
Nümunə
Toplama xərclərini minimallaşdırmaq üçün ədədləri aşağıdakı qaydada əlavə edəcəyik:
və toplayırıq, alırıq. Toplama xərci .
və toplayırıq, alırıq. Toplama xərci .
və toplayırıq, alırıq. Toplama xərci .
Bütün toplamanın ümumi xərci 3 + 6 + 10 = 19.
Alqoritmin həyata keçirilməsi
Giriş ədədlərini çoxüzvlükdə saxlayırıq (ədədlər təkrarlana bilər). İki ən kiçik ədəd çoxüzvlüyün başlanğıcında olur.
multiset<long long> s;Ədədlərin sayını oxuyuruq .
scanf("%lld",&n);Toplamaların ardıcıllıqla oxunması və onları çoxüzvlüyə əlavə edirik.
for (i = 0; i < n; i++)
{
scanf("%lld",&x);
s.insert(x);
}Bütün ədədlərin toplama xərclərini dəyişənində hesablayırıq.
res = 0;Çoxüzvlükdə bir ədəddən çox ədəd olduğu müddətcə onun iki ən kiçik elementini çıxarır və toplayırıq, sonra onların cəmini yenidən -ə əlavə edirik. və ədədlərinin toplama xərci a + b-yə bərabərdir və o, -ə əlavə edilir.
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;
}Çoxüzvlükdə yalnız bir ədəd qaldıqda, cavabı - dəyişəninin dəyərini çıxarırıq.
printf("%lld\n",res);Prioritet növbəsi ilə həyata keçirilməsi
Ən önündə həmişə ən kiçik elementin olduğu prioritet növbəsi elan edirik.
priority_queue<long long, vector<long long>, greater<long long> > pq;Ədədlərin sayını oxuyuruq .
scanf("%lld",&n);Toplamaların ardıcıllığını oxuyur və onları prioritet növbəsinə əlavə edirik.
scanf("%lld",&n);
for (i = 0; i < n; i++)
{
scanf("%lld",&x);
pq.push(x);
}Bütün ədədlərin toplama xərclərini dəyişənində hesablayırıq.
res = 0;Prioritet növbəsi bir ədəddən çox ədəd olduğu müddətcə onun iki ən kiçik elementini çıxarır və toplayırıq, sonra onların cəmini yenidən -yə əlavə edirik. və ədədlərinin toplama xərci a + b-yə bərabərdir və o, -ə əlavə edilir.
while (pq.size() > 1)
{
a = pq.top(); pq.pop();
b = pq.top(); pq.pop();
pq.push(a + b);
res += a + b;
}Prioritet növbəsində yalnız bir ədəd qaldıqda, cavabı - dəyişəninin dəyərini çıxarırıq.
printf("%lld\n",res);Java ilə həyata keçirilməsi
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 ilə həyata keçirilməsi
Ən önündə həmişə ən kiçik elementin olduğu prioritet növbəsi elan edirik.
from queue import PriorityQueue
q = PriorityQueue()Giriş məlumatlarını oxuyuruq.
n = int(input())
lst = map(int,input().split())Toplamaları növbəyə əlavə edirik.
for x in lst:
q.put(x)Bütün ədədlərin toplama xərclərini dəyişənində hesablayırıq.
res = 0Növbədə bir ədəddən çox ədəd olduğu müddətcə onun iki ən kiçik elementini çıxarır və toplayırıq, sonra onların cəmini yenidən -yə əlavə edirik. və ədədlərinin toplama xərci a + b-yə bərabərdir və o, -ə əlavə edilir.
while q.qsize() > 1:
a = q.get()
b = q.get()
q.put(a + b)
res += a + bNövbədə yalnız bir ədəd qaldıqda, cavabı - dəyişəninin dəyərini çıxarırıq.
print(res)