UVA 10954 - Add All
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. 1 #include <iostream>
#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 |
Donghua University