SOJ4459 skysky's game(贪心+优先队列)
天天最近迷上了天天爱消除游戏,现在他觉得这个游戏已经没有意思了。所以他发明一个新的消除游戏。有n堆糖果,每一个糖果有一个重量w,天天每次都选择两个糖果合并为一个糖果,新的糖果的重量等于这两个糖果的重量之和,并且他将获得等价于这两个糖果重量的值。直到只剩下一个糖果为止。现在天天想知道他最后最少获得的值是多少?
Input
第一行包含一个整数t(t<=10),代表组数 对于每一组数据,首先是一个整数n(n<=100000),代表有n堆糖果。接下来有n个数wi(0<=wi<=100000)代表每个糖果的重量。
Output
对于每一组数据,输出一个整数,代表天天最少获得的重量的值。
Sample Input
1 3 1 2 3
Sample Output
9
思路:本题核心是贪心,和哈弗曼树的构造原理相同。每次选取最小的两个数值进行相加,将和加到ans中保存,之后将两者相加的值放回去。不过本题需要注意的是由于返回后需要排序,如果每一次都进行sort()会超时,据shuaishuai说本题使用归并排序好像是可行的,但是没有尝试不清楚。个人推荐用数据结构来进行维护,我是用的优先队列(《挑战程序设计竞赛》P71),保证了时间。
AC代码:
#include <stdio.h> #include <queue> #include <iostream> using namespace std; int main(){ int T; scanf("%d",&T); while(T--){ int n; scanf("%d",&n); priority_queue<int,vector<int> , greater<int> > que; for(int i=0;i<n;i++){ int temp; scanf("%d",&temp); que.push(temp); } long long ans=0; while(que.size()!=1){ int a=que.top();que.pop(); int b=que.top();que.pop(); ans+=a+b; que.push(a+b); } printf("%lld\n",ans); } return 0; }
ps:这个题目由于数据规模较大所以只能使用贪心求解,当数据范围较小时也可以把这个题目理解为区间DP,使用尺取法求解