題目大意:給定 \(n\) 個數,每次能夠任意選兩個數 \(a_i,a_j\) 相加,把相加的結果做爲一個新數繼續執行此操做,直到只剩一個數爲止。現要求使最後得出的這個數最小。ios
一個顯然的貪心策略:每次選最小的兩個數相加,獲得一個新數,而後繼續。可是,若是按照這樣的思路,那麼每次獲得新數後這個序列的單調性就有可能會被破壞。數組
如何解決呢?很顯然的一種方法,將新數加入序列後,再把這個序列排序。然而這樣作彷佛會超時。C++ STL 中提供了一種巧妙地解決方法:\(\mathtt{priority\_queue}\)。它地本質是建一個二叉堆,而後每當插入一個數,就維護這個二叉堆。那麼顯然,在這個題中,咱們須要建一個小根堆,使較小的元素老是先被取出進行操做。less
而後須要解決一個問題:spa
如何創建小根堆(使用\(\mathtt{priority\_queue}\))?code
這樣:priority_queue<int,vector<int>,greater<int> >q;
。其中第一個 int
表明小根堆中存儲的數據類型, vector<int>
表明存儲的方式(vector
就是數組), greater<int>
就是從小到大(即小根堆)。而後大根堆的話就是 priority_queue<int,vector<int>,less<int> >q;
。排序
因而,作法就呼之欲出了:沒讀入一個數字,就插入小根堆中。而後,當元素個數大於等於 2 時循環,每次取出隊首的兩個元素相加,答案加上這個數字,再令新數入隊便可。隊列
請注意:這裏爲何循環條件時元素個數大於等於 2而不是 隊列不爲空 呢?用兔隊的一句話來回答:it
參考代碼:io
#include <iostream> #include <stdio.h> #include <queue> using namespace std; int n,w; priority_queue<int,vector<int>,greater<int> >q; int main() { long long ans=0; scanf("%d",&n); for(int i=1;i<=n;i++){scanf("%d",&w);q.push(w);} while(q.size()>=2) { int x=q.top();q.pop(); int y=q.top();q.pop(); x+=y; ans+=x; q.push(x); } printf("%lld\n",ans); return 0; }