题目描述:
输入输出样例:
输入:
3
1 2 9
输出:
15
说明情况:
方法及其思想:
这题采用贪心思想,找到最小的两种果子进行合并,不断重复,直至只剩下一种果子。
第一种——用stl中的multiset写,不能用set,set会去掉重复元素。
#include <iostream>
#include <algorithm>
#include <set>
using namespace std;
multiset<long long> s;
int n;
long long sum=0;
int main(void){
cin.tie(0);
cout.tie(0);
cin>>n;
long long x;
for(int i=1;i<=n;i++){
cin>>x;
s.insert(x);
}
while(s.size()!=1){
auto fi=s.begin();
auto se=s.begin();
se++;
x=*fi+*se;
sum+=x;
s.insert(x);
s.erase(fi);
s.erase(se);
}
cout<<sum<<endl;
return 0;
}
第二种——用优先队列priority_queue写。
#include <iostream>
#include <queue>
#include <functional>
using namespace std;
int n,x;
long long sum=0;
priority_queue<int,vector<int>,greater<int> >q;
int main(void){
cin>>n;
for(int i=1;i<=n;i++){
cin>>x;
q.push(x);
}
while(q.size()!=1){
int a=q.top();
q.pop();
int b=q.top();
q.pop();
int c=a+b;
sum+=c;
q.push(c);
}
cout<<sum<<endl;
return 0;
}
第三种,运用哈夫曼树中所用的方法,不断循环,找到最小的两个数,并把那两个数设置成已经被选过的状态(我这里用的是有双亲)。
但这种方法效率比较低,两层for循环,所以比较慢。
#include <iostream>
#include <vector>
using namespace std;
int n;
struct Node{
int parent,value;
}a[20010];
long long sum=0;
int main(void){
cin.tie(0);
cout.tie(0);
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i].value;
a[i].parent=0;
}
for(int i=1;i<=n-1;i++){
long long min_c=1e9,min_d=1e9;
int c,d;
for(int j=1;j<n+i;j++){
if(min_c>a[j].value&&a[j].parent==0){
min_d=min_c;
d=c;
min_c=a[j].value;
c=j;
}
else if(min_d>a[j].value&&a[j].parent==0){
min_d=a[j].value;
d=j;
}
}
a[i+n].parent=0;
a[n+i].value=min_d+min_c;
sum+=a[n+i].value;
a[c].parent=n+i;
a[d].parent=n+i;
}
if(n>=2)
cout<<sum<<endl;
else
cout<<a[1].value<<endl;
return 0;
}