农夫约翰为了修理栅栏,要将一块很长的木板切割成N块。准备切成的木块的长度为L1, L2,…Ln,未切割前木板的长度恰好为切割后木板长度的总和。每次切割木板时,需要的开销为这块木板的长度。例如长度为21的木板要切成长度为5,8,8的三块木板。长21的木板切成长为13和8的木板时,开销为21.再将长度为13的板切成长度为5和8的板时,开销为13.于是合计开销时34.请求出按照目标要求将木板切割完最小的开销是多少。
输入格式:
Line 1: One integer N, the number of planks
Lines 2… N+1: Each line contains a single integer describing the length of a needed plank
输出格式:
Line 1: One integer: the minimum amount of money he must spend to make N-1 cuts
输入:
3
8 5 8
输出:
34
法一:
优先队列(priority_queue),更方便简洁,很好地利用到STL的优势
#include <iostream>
#define LL long long
using namespace std;
priority_queue<int,vector<int>,greater<int> >q;
int main(){
int n;
cin>>n;
int x;
for(int i=0;i<n;i++){
cin>>x;
q.push(x);
}
LL sum=0;
while(q.size()>1){
int m1=q.top();
q.pop();
int m2=q.top();
q.pop();
sum+=m1+m2;
q.push(m1+m2);
}
cout<<sum<<endl;
}
法二:
#include <iostream>
#define LL long long
using namespace std;
int a[N];
int main(){
int n;
cin>>n;
for(int i=0;i<n;i++){
cin>>a[i];
}
sort(a,a+n);
LL res=0;
LL sum=0;
while(n>1){
int m1=0,m2=1; //最小两数的下标,m1最小,m2次小
if(a[m1]>a[m2]){
int t=m1;
m1=m2;
m2=t;
}
for(int i=2;i<n;i++){
if(a[i]<a[m1]){ //出现比最小的小的数,更新状态
m2=m1;
m1=i;
}
else if(a[i]<a[m2]){ //比次小的小,比最小的大
m2=i;
}
}
res=a[m1]+a[m2];
sum+=res;
if(m1==n-1){
int t=m1;
m1=m2;
m2=t;
}
a[m1]=res;
a[m2]=a[n-1];
n--;
}
cout<<sum<<endl;
return 0;
}