题目很长,要求巨多,仔细看完换种说法就是:要用最少的容器,把一堆东西平均分,不能超过容量上限,不能超过规定数量。这么说很明显就是贪心算法了。
题目要求一组里最多不能超过两个物品,最重要的是要求每组价值相差较小,所以每组里的物品需要一大一小地搭配,这时候需要我们把物品价值排个序,排序算法可多了,最简单的就是桶排序:
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;
}