【51Nod - 1117】【聰明的木匠 】
阿新 • • 發佈:2018-11-01
題目:
一位老木匠需要將一根長的木棒切成N段。每段的長度分別為L1,L2,......,LN(1 <= L1,L2,…,LN <= 1000,且均為整數)個長度單位。我們認為切割時僅在整數點處切且沒有木材損失。
木匠發現,每一次切割花費的體力與該木棒的長度成正比,不妨設切割長度為1的木棒花費1單位體力。例如:若N=3,L1 = 3,L2 = 4,L3 = 5,則木棒原長為12,木匠可以有多種切法,如:先將12切成3+9.,花費12體力,再將9切成4+5,花費9體力,一共花費21體力;還可以先將12切成4+8,花費12體力,再將8切成3+5,花費8體力,一共花費20體力。顯然,後者比前者更省體力。
那麼,木匠至少要花費多少體力才能完成切割任務呢?
Input
第1行:1個整數N(2 <= N <= 50000)
第2 - N + 1行:每行1個整數Li(1 <= Li <= 1000)。
Output
輸出最小的體力消耗。
Sample Input
3
3
4
5
Sample Output
19
解題報告:貪心的題目,一想就知道要每次先把最長的截斷,然後自己就傻傻的按照他給的段長排序,入坑了,其實思考到了這是個可以從小段向長進展的,一個逆推的過程,自己忽略一點就是小段之和 可能會大於之後的段長,那麼之前的排序就是不合理的了。所以說正解就是優先佇列,自己需要每次更新,將其中最小的兩個踢出去,將二者的和壓進去。
ac程式碼:
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<queue> using namespace std; typedef long long ll; const int maxn=50008; ll num[maxn]; ll sum[maxn]; priority_queue<ll,vector<ll> ,greater<ll> > q; int main() { int n; while(scanf("%d",&n)!=EOF) { while(q.size()) q.pop(); for(int i=0;i<n;i++) { cin>>num[i]; q.push(num[i]); } ll ans=0; while(q.size()>1) { ll a,b; a=q.top(); q.pop(); b=q.top(); q.pop(); ans+=(a+b); q.push(a+b); } printf("%lld\n",ans); } }