附上C语言代码
#include<stdio.h>
int total = 0;//搬运果子需要的总力气,设为全局变量
void MergeSort(int a[],int s,int e,int temp[]);//归并排序基本操作
void Merge(int a[],int s,int m,int e,int temp[]);// 归并排序基本操作
int main()
{
int n;
scanf("%d",&n);
int fWight[n];//储存果子重量的数组
int temp[n];
for(int i = 0;i < n;i++)
{
scanf("%d",&fWight[i]);
}
MergeSort(fWight,0,n - 1,temp);//将重量从小到大排序
while(n > 1)
{
total += (fWight[0] + fWight[1]);//每次取最前面的两堆果子合并,然后将后面的数组元素整体前移
fWight[0] += fWight[1];
for(int i = 1;i < n - 1;i++)//元素前移
fWight[i] = fWight[i + 1];
n--;//数组元素个数减一
for(int i = 0;i < n - 1;i++)
{
if(fWight[i] > fWight[i + 1])//这里再用快排或者归并会超时,所以就选择了线性方法
{ //将第一个元素与后面每一个元素比较,如果后面的元素大就交换
int temp = fWight[i]; // 因为其他元素都是排好序的,交换完成后,就又是一个从大到小排序的
fWight[i] = fWight[i + 1];//数组,重复操作直到n=1
fWight[i + 1] = temp;
}
}
}
printf("%d",total);//输出结果
return 0;
}
//下面都是归并排序,就不多说了,以后可以写一个专门说归并排序的,这里偷个懒,但是还要提一句的是,
//归并排序的时间复杂度和快排是一样的,但是空间复杂度较高,这道题有时间复杂度的限制,所以用常规排序会超时
//C++选手也可以用sort函数,C语言没有,我就自己写了,sort函数的时间复杂度和快排一样
void MergeSort(int a[],int s,int e,int temp[])
{
if(s < e)
{
int m = s + (e - s) / 2;
MergeSort(a,s,m,temp);
MergeSort(a,m + 1,e,temp);
Merge(a,s,m,e,temp);
}
}
void Merge(int a[],int s,int m,int e,int temp[])
{
int pb = 0;
int p1 = s,p2 = m + 1;
while(p1 <= m&&p2 <= e)
{
if(a[p1] < a[p2])
temp[pb++] = a[p1++];
else
temp[pb++] = a[p2++];
}
while(p1 <= m)
temp[pb++] = a[p1++];
while(p2 <= e)
temp[pb++] = a[p2++];
for(int i = 0;i < e - s + 1;i++)
a[s + i] = temp[i];
}
删除线格式
这道贪心题要求花费的力气最小,想要枚举的同学肯定会超时的,但是我们会发现,只要每回合并的果堆是所有果堆中重量最小的两堆,每次就能花费最小的力气,根据贪心逻辑,最终花费的力气也一定最小。有一个地方去要注意,在对更新过的数组进行再排序时不能继续用时间复杂度为nlog(n)的算法(快排,归并排序),因为会超时(我第一次就超时了),所以我们改用线性的交换方法,时间复杂度为n,**将合并后的元素(第一个元素)与后面的元素逐一比较,如果后面的元素比较小就交换两个元素,**所以合并后的元素就能被换到合适的位置,一旦它被换到合适的位置 ,因为其他元素本来就是有序的,下一次排序也就结束了,然后重复上面的操作就可以AC了。
我这里用的归并排序,但是在这篇文章中我没有讲,有兴趣的同学可以给我留言,我会更新一篇讲快排和归并文章。
溜了溜了~~