中矿大新生赛 G 甄总搬石头【优先队列/哈夫曼/贪心】
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld
题目描述
https://www.nowcoder.com/acm/contest/41/G
现在草地上有n堆石头,甄总想要合并这n堆石头成为1堆,但是他每次能力有限,所以只能一次合并2堆石头至1堆。
现在已知第i堆石头有ai块,假设甄总要合并第i堆和第j堆石头,则需要花费ai+aj的力气。
给出n堆石头每堆石头的个数,求出甄总要合并n堆成1堆石头一共需要多少力气。
输入描述:
第1行输入一个整数n,代表一共有n堆石头。
第2行输入n个整数ai,表示第i堆有ai块石头。
输出描述:
输出一行整数,表示一共需要多少力气。
示例1
输入
3 1 2 3
输出
9
【分析】:又是一道披着DP-石子归并外衣,仔细读题发现不是DP的题目!和codeforces A.分披萨一样的!因为不是相邻。
//经典贪心问题,用堆维护力气中的最小值,每次从堆中取出最小的两个,计算总和并将总和放回堆中,累加得出结果。(合并果子问题)
【代码】:
#include <bits/stdc++.h> using namespace std; const int maxn =1e5+10; #define LL long long LL a[maxn]; priority_queue <int,vector<int>,greater<int> > q; int n,x,sum=0; int main() { int a,b; ios::sync_with_stdio(false); cin.tie(0);cout.tie(0); cin>>n; for(int i=0;i<n;i++) { cin>>x; q.push(x); } while(q.size()!=1) { a=q.top(); q.pop(); b=q.top(); q.pop(); q.push(a+b); sum+=a+b; } cout<<sum<<endl; return 0; }