洛谷P1090合并果子,贪心算法 纯C语言

附上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了。

我这里用的归并排序,但是在这篇文章中我没有讲,有兴趣的同学可以给我留言,我会更新一篇讲快排和归并文章。

溜了溜了~~

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值