题目描述
农夫John要修理牧场的一段栅栏,他测量了栅栏,发现需要N(1<= N <= 20000)块木头,每块木头长度为Li(1<= Li <=50000)个单位。于是他购买了一条很长的、能锯成N块 的木头(即该木头长度是Li的总和)。农夫John忽略“损耗”,即忽略锯的时候产生锯末而造成的长度损耗。
农夫John没有锯子,于是他去找农夫Don,向他借锯子。
Don是一个守财奴,他不把锯子锯子借给John,而是要John为在木头上锯N-1次支付每一次锯的费用。锯一段木头要支付的费用等于这段木头的长度,即锯长度为21 的木头就要支付21美分。
例如,要将长度为21的木头锯成长度为8,5和8 的三段。
第一次锯木头花费为21,将木头锯成13和8;第2次锯木头花费13,将长度为13的木头锯成8和5;这样总的花费是21+13=34。如果将长度为21 的木头第一次锯成16和5的木头,则第二次锯木头要花费16,总的花费是37(大于34)。
Don让John决定在木头上切得次序和位置。请你帮助John确定锯N块木头索要花费的最少的钱。
输入
第1行: 一个整数N,表示木头的块数;
第2~N+1行: 每行给出一个整数,表示一段需要的木块长度。
输出
第1行: 一个整数,表示N-1次需要支付的最少费用。
样例输入 复制
3
8
5
8
样例输出 复制
34
- 这个题目并不是很难,如果我们要求出最少的钱,那我们就要保证,我每次锯断的木头都要使接下来花费最小,那么到最后锯下来的一定是俩块最小的。
- 那么如何保证上述说法,排序。感觉走到哪里都离不开排序,我使用的是快排。
- 我们保证最小,那么我们就从最小的俩块木头开始,起初的花费就是俩块木头相加,如何我们要记下这个值,因为还要和接下来的木头相加组成那一次锯断的长度,也是锯断的费用。
- 总和sum都要加上t,t为前一块木头和这一块木头的总和(相当于接合的过程啦)
代码如下:
#include<stdio.h>
int a[100020];
int qsort(int left,int right)
{
if(left>right) return 0;
int i,j,temp=a[left],t;
i=left,j=right;
while(i<j)
{
while(i<j&&a[j]>=temp) j--;
while(i<j&&a[i]<=temp) i++;
if(i<j)
{
t=a[i];a[i]=a[j];a[j]=t;
}
}
a[left]=a[i];
a[i]=temp;
qsort(left,i-1);
qsort(i+1,right);
}
int main()
{
int n,i,j;
unsigned long long sum=0,t;
scanf("%d",&n);
for(i=0;i<n;i++)
{
scanf("%d",&a[i]);
}
qsort(0,n-1);
sum=a[0]+a[1];
t=sum;
for(i=2;i<n;i++)
{
t+=a[i];
sum+=t;
}
printf("%llu\n",sum);
}