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
",ans);
    }
    return 0;
} 

ps:这个题目由于数据规模较大所以只能使用贪心求解,当数据范围较小时也可以把这个题目理解为区间DP,使用尺取法求解

原文地址:https://www.cnblogs.com/87hbteo/p/7284361.html