计蒜客-程序设计:轻重搭配 (贪心)(C++)

计蒜客-程序设计:轻重搭配 (贪心)(C++)

一、题目描述

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

输出格式
一个整数,表示最少需要购买的门票数目

样例输入
6
1 9 7 3 5 5
样例输出
4

二、思路

这道题第一次思考时常见有三种思路:

1.先对输入进行从小到大排序后,从前向后遍历,例如1 3 6 7,从 1开始,3符合1的配对条件,那么1,3配对,剩下6,7两张,一共是3张票,这样做的结果是,3本来可以和6或7进行配对,而1和6,7种的另一个配对,只需两种票,可以看出,这里我们讲3这个较小的数字“浪费了”,我们并没有很合理的使用3。

2.从排序序列的首部和尾部开始配对,例如 1 3 5 7,我们将1和7进行配对,然后3和5两张票,一共三张票。这样做的结果是,7本来可以和3进行配对,然后5和1进行配对,这样也只需两张票,然后我们用7来和1进行配对,对于7这个较大的数字,我们也没有很合理的使用它,即我们“浪费了”一个较大的数字。

3.有了前面两种错误思路的经验,我们可以知道,在配对时,我们即不能浪费较小的数字,也不能浪费较大的数字,即要让较大的数字和较小的数字都能得到合理的使用。而且还有一个重要的条件时,假设一组数据中每个人都可以找到和他匹配的人,那么我们最多可以少买一般的票,也就是n/2的票,n为人数,所以先对数据从正中间进行划分,即 1 3 || 5 7,然后依次从每一段的最后面开始匹配,如果匹配成功,则同时向前一位,若不成功,则说明前面小体重的人的体重还是有一些大,不能和后面大体重的人配对,所以我们让前面的人再往前一位,知道小体重的人被遍历完。写到这里我们可以看出,只需要一个while循环即可实现上述的思路。
代码如下:

三、代码

#include <iostream>
#include <algorithm>

using namespace std;

const int N = 6e5;

int n, a[N];

int main()
{
    cin >> n;
    for (int i = 1; i <= n; i ++ )
        cin >> a[i];

    sort(a, a + n + 1);
                                                                                                                                                                                                                                                   
    int count = 0;
    int l = n/2, r = n;   // 分别从n/2 和 n开始遍历
    while (l >= 1 && r >= n/2) {
        if (a[r] >= 2*a[l]) {   //符合
            count++;
            r--;
            l--;
        }
        else 
            l--;

    }
    ///
    cout << n - count;
    return 0;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值