B - 程序设计:轻重搭配

B - 程序设计:轻重搭配


题目

n 个同学去动物园参观,原本每人都需要买一张门票,但售票处推出了一个优惠活动,一个体重为 xx 的人可以和体重至少为 2x2x 配对,这样两人只需买一张票。现在给出了 nn 个人的体重,请你计算他们最少需要买几张门票?

输入格式

第一行一个整数n,表示人数。
第二行n个整数,每个整数Ai表示每个人的体重。

输出格式

一个整数,表示最少需要购买的门票数目。

数据范围

对于30%的数据:1 <= n <= 25, 1 <= Ai <= 100。
对于60%的数据:1 <=n <=10000, 1 <= Ai <= 1000。
对于100%的数据:1 <= n <= 5 ·10 ^ 5,1 <= Ai <= 10^5。

样例解释

1 和 99 配对,77 和 33 配对,剩下 5,55,5 单独,一共买四张票。

Sample Input

6
1 9 7 3 5 5

Sample Output

4


思路注意点

1.首先需要做的就是排序,但是当n达到50万时候,冒泡排序,选择排序等一定会超时,那就需要用到快速排序了。
2.排序过后最少需要买的票数,就需要最合理的选择匹配对象,防止小的数字和最大的数字匹配造成最大的数字的浪费。
步骤如下:
(1)n / 2为一个分解点,让i = n / 2即让i站在竖线的左边,让 j = n,即让n站在最后边。
在这里插入图片描述
(2)让 i 和 j进行匹配,如果没有成功,i–,i向前一个推进。
在这里插入图片描述
(3)当i 和 j匹配成功时候,计票数+1,两人算一票,然后i 和 j共同向前移动,继续寻找下一轮。
在这里插入图片描述
(4)
在这里插入图片描述
(5)当所有匹配完成后,就会余下几个没有匹配成功的人,那么这几个人就需要单独买票了,那么余下的人怎么计算呢,我们知道匹配成功的人,是cnt * 2,那么用总人数减去cnt * 2就是余下的人数。
在这里插入图片描述


代码如下

#include<stdio.h>
int n,i,j,a[1000000];  //定义全局变量 

void quicksort(int left, int right)   
{
	int temp,t;   //temp变量是基准,t变量是用来交换的第三变量 
	if(left > right)   //跳出循环的第一个条件 
	{
		return;
	}
	
	temp = a[left];   //此时选用的是第一个数当做基准 
	i = left;     //i是1 
	j = right;     //j是n 
	while(i != j)     //当i,j没有走到一块的时候 
	{
		while(a[j] >= temp && i<j)   //j一步一步左移,查找比基准值小的数 
		{
			j--;
		}
		while(a[i] <= temp && i<j)   //i一步一步右移,查找比基准值大的数 
		{
			i++;
		}
		if(i < j)
		{
			t = a[i];    //将j查到的比基准值的数与i查到的比基准值小的数交换 
			a[i] = a[j];  //即将小的数放在基准值左边 
			a[j] = t;      //将大的数放在基准值右边 
		}
	}
	  //将基准值归位 
	a[left] = a[i];    //当循环结束时,i=j,在中间某一位置 
	a[i] = temp;      //将那一位置的数与基准值交换 
	
	//递归 ,将基准值左边分为一部分
   //将基准值右边分为一部分 
	quicksort(left,i-1);     //继续处理左半部分的数    
	quicksort(i+1,right);   //继续处理右半部分的数 
	return ;
}
int main()
{
	while(scanf("%d",&n) != EOF)
	{	
			int i,j;
			for(i=1; i<=n; i++)
			{
				scanf("%d",&a[i]);
			}
			//快速排序
			quicksort(1,n);

			int cnt = 0;
			i = n / 2;
			j = n;
			while(i)
			{
				if(a[j] >= 2 * a[i])
				{
					cnt++;
					i--;
					j--;
				}
				else
				{
					i--;
				}
			}
			int sum = (n - 2 * cnt + cnt);
			printf("%d",sum);
			
		
	}
}

运行结果
在这里插入图片描述


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值