组队竞赛(C++)

题目链接

组队竞赛

题目描述与示例

牛牛举办了一次编程比赛,参加比赛的有3*n个选手,每个选手都有一个水平值a_i.现在要将这些选手进行组队,一共组成n个队伍,即每个队伍3人.牛牛发现队伍的水平值等于该队伍队员中第二高水平值。
例如:
一个队伍三个队员的水平值分别是3,3,3.那么队伍的水平值是3
一个队伍三个队员的水平值分别是3,2,3.那么队伍的水平值是3
一个队伍三个队员的水平值分别是1,5,2.那么队伍的水平值是2
为了让比赛更有看点,牛牛想安排队伍使所有队伍的水平值总和最大。
如样例所示:
如果牛牛把6个队员划分到两个队伍
如果方案为:
team1:{1,2,5}, team2:{5,5,8}, 这时候水平值总和为7.
而如果方案为:
team1:{2,5,8}, team2:{1,5,5}, 这时候水平值总和为10.
没有比总和为10更大的方案,所以输出10.

输入描述:

输入的第一行为一个正整数n(1 ≤ n ≤ 10^5)
第二行包括3*n个整数a_i(1 ≤ a_i ≤ 10^9),表示每个参赛选手的水平值.

输出描述:

输出一个整数表示所有队伍的水平值总和最大值.

示例:

输入:

2
5 2 8 5 1 5

输出:

10

解题思路

题目分析

​ 根据题目的描述,总结下来就是需要输入一个n表示n组,输入3*n个数据表示每个队员的水平值,然后再3人一组,最后对n个组的第二大水平值进行求和即可。

个人思路

  1. 将3n个数据排序
  2. 最小的n个数必定是每组的第三水平值
  3. 最大的n个数必定是每组的第一水平值
  4. 取中间n个数求和即可

上述思路就是我看到此题目的第一反映,然后就报错了。。。。
在这里插入图片描述
我们拿题目数据分析:
在这里插入图片描述

按上述说法去头去尾取到中间的5+5=10,乍一看好像又没有问题(没错,我就是这么被骗的,然后惨遭报错)

我们换下面一组数据:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LjOG6s2a-1652951914057)(C:\Users\lwz\AppData\Roaming\Typora\typora-user-images\image-20220519165346646.png)]

去头去尾取4+5+6=15,但是我们看这样一个分组:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Awr3Vmh2-1652951914057)(C:\Users\lwz\AppData\Roaming\Typora\typora-user-images\image-20220519165521929.png)]

取的值8+6+4=18是比我的那种更优的,斟酌思考后发现了我的问题所在:我的思路直接舍弃掉了次大的数据,使用两大带一小的取法可以让次大的数据保留下来从而提高水平值,进一步使得水平值总和更大。

正确思路:

  1. 将3n个数据排序
  2. 从第n+1个数隔1取1

ps:如上述1-9,从4开始取隔一个5取6,再隔一个7取8即可

代码展示

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;

int main()
{
    int n;
    vector<int> score;
    while(cin>>n)//支持循环输入
    {
        //设置vector的大小
        score.resize(3*n);
        for(int i=0;i<score.size();i++)
        {
            cin>>score[i];
        }
        //算法库中的排序算法,默认升序
        sort(score.begin(),score.end());
        
        //由于给定的分数范围1 ≤ a_i ≤ 10^9,int类型可能会超出范围导致跑不过
        long long sum=0;
        
        //前n个是最小的数据直接从第n+1个数据隔2相加(中间的那个数字是一组的最高水平)
        for(int i=n;i<3*n;i+=2)
        {
            sum+=score[i];
        }
        cout<<sum;
    }
    return 0;
}

题解

关于我看到的题解,前面一直到排序都是基本一样,但是在选择数据的时候题解采用的方式好像又不太一样:

我的:
for(int i=n;i<3*n;i+=2)
{
	sum+=score[i];
}

题解:
for(int j=0;j<n;j++)
{
    sum+=score[score.size()-2*(j+1)];
}

目前我也不是很能理解这个公式的原理,后续理解了再更新一下吧。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值