修理牧场,锯栅栏

题目描述

农夫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

 

  1. 这个题目并不是很难,如果我们要求出最少的钱,那我们就要保证,我每次锯断的木头都要使接下来花费最小,那么到最后锯下来的一定是俩块最小的。
  2. 那么如何保证上述说法,排序。感觉走到哪里都离不开排序,我使用的是快排。
  3. 我们保证最小,那么我们就从最小的俩块木头开始,起初的花费就是俩块木头相加,如何我们要记下这个值,因为还要和接下来的木头相加组成那一次锯断的长度,也是锯断的费用。
  4. 总和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);
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值