【算法分析】
贪心选择:选择其中果子数量最小的两堆进行合并。
先用初始数据构造小根堆,每次选择最小的两个出堆。相加后再插入构造小根堆,直到只剩下最后一堆。
【参考代码】
代码1:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <cmath>
using namespace std;
int heap[100001],heap_len;//堆数组
int n,x,y,i,sum=0;
void put(int t){//将t加入小根堆
int now,next;
heap[++heap_len]=t;
now=heap_len;
while(now>1){
next=now/2;
if(heap[now]>=heap[next]) return;
swap(heap[now],heap[next]);
now=next;
}
}
int get(){//弹出小根堆顶元素
int next,tot,now;
tot=heap[1];
heap[1]=heap[heap_len--];
now=1;
while(2*now<=heap_len){
next=2*now;
if(next<heap_len&&heap[next+1]<heap[next])
next++;
if(heap[next]>=heap[now]) return tot;
swap(heap[now],heap[next]);
now=next;
}
return tot;
}
int main()
{
scanf("%d",&n);
for(i=1;i<=n;i++){
scanf("%d",&x);
put(x);
}
for(i=1;i<n;i++){
x=get();
y=get();
sum+=x+y;
put(x+y);
}
printf("%d\n",sum);
return 0;
}
代码2:优先队列
#include <bits/stdc++.h>
using namespace std;
int main()
{
priority_queue<int, vector<int>, greater<int> > pq;//小顶堆
int n, a, sum = 0;//sum:体力加和
cin >> n;
for(int i = 1; i <= n; ++i)
{
cin >> a;
pq.push(a);
}
while(pq.size() > 1)
{
int a = pq.top();
pq.pop();
int b = pq.top();
pq.pop();
sum += a+b;//体力增加这次合并后的果堆中果子的数量
pq.push(a+b);
}
cout << sum;
return 0;
}