蓝桥杯:纪念品分组

        题目很长,要求巨多,仔细看完换种说法就是:要用最少的容器,把一堆东西平均分,不能超过容量上限,不能超过规定数量。这么说很明显就是贪心算法了。

        题目要求一组里最多不能超过两个物品,最重要的是要求每组价值相差较小,所以每组里的物品需要一大一小地搭配,这时候需要我们把物品价值排个序,排序算法可多了,最简单的就是桶排序:

int arr2[1000000];

void tongpaixu(int arr[])
{
    for(int i=0;i<n;i++)
    {
        arr2[arr[i]]++;
    }
}

也可以发现桶排序缺点很明显,需要的空间太大了,浪费的空间太多了,数据足够大的时候,时间消耗的也太久了,而且还不能保证数组开的范围包括了所有的数据,然后是冒泡排序,但缺陷也很明显,冒泡排序一个个数据换位置,如果碰到足够多的数据的时候,时间消耗也很大。

        最经典也最广为人知的就是快速排序了:

int a[100001];

void quicksort(int left,int right)
{
	int i,j,t,temp;
	if(left>right)
	{
		return;
	}
	
	temp=a[left];
	i=left;
	j=right;
	while(i!=j)
	{
		while(a[j]>=temp && i<j)
		{
			j--;
		}
		while(a[i]<=temp && i<j)
		{
			i++;
		}
		if(i<j)
		{
			t=a[i];
			a[i]=a[j];
			a[j]=t;
		}
	}
	a[left]=a[i];
	a[i]=temp;
	
	quicksort(left,i-1);
	quicksort(i+1,right);
}

快速排序,顾名思义,时间消耗少,但也是相对而言,在大量存在相同数据的时候,时间复杂度会和冒泡排序差不多,也会有很多优化版本,例如增加随机选取参考数函数进行分割快排,又或者将挨在一团的相同数据打乱在数组中再进行快排,又或者在还剩一部分数据的时候用冒泡排序,时间复杂度会比快排低等等,这些优化我只有了解,还没有掌握。

        而最简单的,最偷懒的,就是使用c++自带的库函数sort()。

    int p[n]={0};
	for(int i=0;i<n;i++)
	{
		cin >> p[i];
	}
	sort(p,p+n);

然后就可以简单的贪心了,从排好序的数组最小的和最大的两头双向开始,如果小的加上大的价值低于要求价值,那就可以分在一组里,然后小的往大的方向移一位,大的往小的移一位:

if(p[i]+p[j]<=w)
{
    sum++;
    i++;
    j--;
}

如果大的加上小的超过要求价值了,那就大的单独为一组,小的不动,大的往小的移一位:

else if(p[j]<=w)
{
    sum++;
    j--;
}

如果当i和j碰到一起了,就说明只剩这一个了,那就只能单独为一组:

else if(i==j)
{
    sum++;
}

最后输出sum,就是最终的组数。

上代码:

#include <bits/stdc++.h>

using namespace std;

int main()
{
	int w,n,sum;
	cin >> w >> n;
	int p[n]={0};
	for(int i=0;i<n;i++)
	{
		cin >> p[i];
	}
	sort(p,p+n);
	int i=0,j=n-1;
	while(i<=j)
	{
		if(p[i]+p[j]<=w)
		{
			sum++;
			i++;
			j--;
			continue;//怕运行到下面的情况,可能是我多此一举
		}
		else if(p[j]<=w)
		{
			sum++;
			j--;
			continue;
		}
		else if(i==j)
		{
			sum++;
			break;//怕没有及时结束循环,可能是我多此一举
		}
	}
	
	cout << sum;
	
	return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AtlanticDrift

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值