合并果子
很显然就是一个哈夫曼树的题目。
每个堆都是下面的一个叶子节点,合并的结果就是3a+3b+2c+2d+2e。如果想让这个值最小,很显然就是让最小的数值放在层次最深的节点中。
实现方法
维护一个小根堆,每次都取最小的两个点求和(一次合并果子堆的过程),然后将新的节点加入小根堆中(构造霍夫曼树的过程)。依此类推直到堆中只剩下一个元素。
小根堆用
#include #include
priority_queue<int, vector, greater> heap;
#include<iostream>
#include<queue>
#include<vector>
using namespace std;
priority_queue<int, vector<int>, greater<int>> heap;
int main(){
int n;
cin>>n;
for(int i=1;i<=n;i++){
int a;cin>>a;
heap.push(a);
}
int ans=0;
while(heap.size()>1){
int a=heap.top();heap.pop();
int b=heap.top();heap.pop();
ans+=(a+b);
heap.push(a+b);
}
cout<<ans<<endl;
return 0;
}
排队打水
类似短作业优先呗,本题贪心思想比较容易理解
#include<iostream>
#include<algorithm>
using namespace std;
const int N=1e5+10;
int main(){
int n;
cin>>n;
int a[N];
for(int i=1;i<=n;i++){
cin>>a[i];
}
sort(a+1,a+1+n);
long long ans=0;
for(int i=1;i<=n-1;i++){
ans+=(a[i]*(n-i));
}
cout<<ans<<endl;
return 0;
}
货仓选址***
这题其实就是一个绝对值不等式
因此本题代码就很好写了
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
const int N=1e5+10;
int n;
int a[N];
int main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
}
sort(a+1,a+1+n);
long long ans=0;
//因为奇数偶数仅仅是在x选择上不同,结果都是一样的
for(int i=1;i<=n/2;i++){
ans+=(a[n-i+1]-a[i]);
}
cout<<ans<<endl;
return 0;
}
耍杂技的牛**
#include<iostream>
#include<algorithm>
using namespace std;
const int N=1e5+10;
struct node{
long long a,b;
long long w;
}cow [N];
int n;
int cmp(node a, node b){
return a.w<b.w;
}
int main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>cow[i].a>>cow[i].b;
cow[i].w=cow[i].a+cow[i].b;
}
sort(cow+1,cow+1+n,cmp);
int ans=-0x3f3f3f3f;
int res=0;//上面所有牛的重量
for(int i=1;i<=n;i++){
//计算每一头牛的风险值
res+=cow[i-1].a;
if(ans<(res-cow[i].b))
ans=res-cow[i].b;
}
cout<<ans<<endl;
return 0;
}