洛谷-P4447-分组

[AHOI2018初中组]分组 - 洛谷


解题思路:

1.看到这道题,可以想到贪心和排序,将n个数字进行从 小到大的排序,然后依次遍历,找到连续的数中最小 的那个数,输出即可,但是只能得40分,因为一旦涉 及到数据有重复的,便无法进行正常分组

2 首先分析,分组的设置必须为连续性的,而且不能有 相同实力值的存在,那么一旦有相同的存在,需要放 在另一个组里,那么如何保证连续性呢?其实就是最后 一个数加1等于要加进来的数,就能保证连续性,所 以,可以想到利用数组来模拟队列

3. 队列是一种数据结构,只能从队尾添加元素,那么如 果用数组来模拟的话,我们永远只考虑队尾的元素即 可,如果满足可以插入队列,队尾元素更新,队内元 素个数+1,如果不满足,那么新开一个队列,将这个数 设置为队列的末尾元素,并且元素个数为1

4. 接下来考虑需要用多少数组,数组a用来存放n个数 据,并从小到大排序,数组dui用来存放每个队列队尾 的元素,数组num用来存放对应队列的元素个数

5. 接下来就是将n个元素进行挨个插入,这里有一个问 题,要保证队列元素个数最少的最大,什么意思呢? 如果现在待插入的元素是2,符合条件的有两个小 组,0,1和-1,0,1,为了保证分组人数平均,那么肯定要 选择第一个分组插入,所以还要遍历所有队列元素找到符合条件的队列中个数最小的那个组

6. 最后,将num数组中的最小值输出即可


#include<bits/stdc++.h>
using namespace std;
int a[100005],dui[100005],num[100005];
int main()
{
	int n;
	cin>>n;
	for(int i=1;i<=n;i++)
	cin>>a[i];

	sort(a+1,a+n+1);//对存进去的数从小到大排序

	dui[1]=a[1];//将第一个数插入到第一个队列的末尾中 
	num[1]=1; //第一个队列的数量为1

	int cnt=1;//记录队列的个数 
	for(int i=2;i<=n;i++)
	{
		bool find=0;//标记此时的a[i]能否插入到队列中
		for(int j=1;j<=cnt;j++)
		if(dui[j]+1==a[i])//如果可以插入到队列中 
		find=1;//标记find为1 

		if(find==0)//如果没有队列可以插入 
		{
			cnt++;//新开一个队列 
			dui[cnt]=a[i];//将这个数放入到新开的队列中
			num[cnt]=1;//这个队列此时的元素个数为1 
		}
		else//如果有队列可以插入 
		{
			int min=10000000;
			int temp;//设置书签,为满足插入的元素最少的队列编号 
			for(int k=1;k<=cnt;k++)//遍历整个队列 
			{
				if(dui[k]+1==a[i])//如果这个队列满足 
				{
					if(num[k]<min)
					{
						min=num[k];
						temp=k;
					}//找到符合条件的元素最少的队列编号 
				}
			}
			dui[temp]=a[i];//更新这个队列的末尾元素 
			num[temp]++; //这个队列的元素个数加1 
		} 
	}
	int min=10000000;
	for(int i=1;i<=cnt;i++)
	if(num[i]<min)
	min=num[i];

	cout<<min;
	return 0;
 } 

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值