http://uva.onlinejudge.org/external/109/10954.html
题意:
输入一串数据,拿出两个相加,把和放回去,再拿出两个相加,把和放回去……依次循环,最后找出最小的和。
思路:
使用优先队列+贪心,队列按从小到大排列,每次选出队首最小的2个数据,计算之后把和再放回队列。也就是哈夫曼编码算法。
Using a Priority Queue, you can greedily take the two smallest numbers, add them and insert them back into the Priority Queue.
#include <iostream>
#include <queue>
#include <cstdlib>
#include <cstdio>
#include <cstring>
using namespace std;
class T{
public :
int n;
};
bool operator < (const T &t1, const T &t2)
{
return t1.n > t2.n;
}
class AddAll{
private:
priority_queue<T> pri_que;
int sum;
public:
void init();
void process();
// void output();
};
void AddAll::init(){
while(!pri_que.empty())pri_que.pop();
sum = 0;
}
void AddAll::process(){
int num;
T temp;
while(cin>>num){
if (num == 0)break;
init();
while(num--){
cin>>temp.n;
pri_que.push(temp);
}
while(!pri_que.empty()){
T top1 ,top2 ,sumTop;
top1 = pri_que.top();
pri_que.pop();
if(!pri_que.empty()){
top2 = pri_que.top();
pri_que.pop();
}
else
top2.n = 0;
sumTop.n = top1.n + top2.n;
sum = sumTop.n + sum;
if(!pri_que.empty())
pri_que.push(sumTop);
}
cout<<sum<<endl;
}
}
int main()
{
// #ifndef ONLINE_JUDGE
// freopen("D:\\acm.txt","r",stdin);
// #endif // ONLINE_JUDGE
AddAll addall;
addall.process();
return 0;
}
注意:要重载'<',使优先队列从小到大排列。
测试数据:
数据来源:http://www.algorithmist.com/index.php?title=UVa_10954
Input
3 1 2 3 4 1 2 3 4 10 100000 100000 100000 100000 100000 100000 100000 100000 100000 100000 5 2 2 2 2 3 0 |
Output
9 19 3400000 26 |