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);
}
}
运行结果
: