首页 > 试题广场 >

组队竞赛

[编程题]组队竞赛
  • 热度指数:3514 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32M,其他语言64M
  • 算法知识视频讲解
牛牛举办了一次编程比赛,参加比赛的有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),表示每个参赛选手的水平值.


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

输入

2
5 2 8 5 1 5

输出

10
//最小和最大次大组队,次小和第三大第四大组队……
//如,123456789
//下标012345678
//组队方案如下:
//189,267,345 水平值总和为8+6+4=18,是最大值
//每队队员中第二高水平值的下标:size-2*i(i=1,2,...,n)
//所有队伍的水平值总和=每队队员中第二高水平值的总和
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int main() {
    int n = 0;//声明n,表示组数
    while (cin >> n)//输入n
    {
        vector<int> a;//存放每个选手的水平值
        a.resize(3 * n);//扩容
        for (int i = 0; i < 3 * n; ++i)
        {
            cin >> a[i];//输入每个选手的水平值
        }
        sort(a.begin(), a.end());//给选手的水平值排序
        long long sum = 0;//声明sum,表示总和,值可能很大,用long long类型
        for (int i = 1; i <= n; ++i)
        {
            sum += a[a.size() - 2 * i];//sum累加
        }
        cout << sum << endl;//输出sum
    }
    return 0;
}

发表于 2023-03-25 14:06:13 回复(0)
先排序
假设排序后是: 1 2 3 4 5 6 7 8 9
1 和 8 9 为一组
2 和 6 7 为一组
3 和 4 5为一组
每组第二大的数字为 8 6 4
其 size=9 ;  
下标 3 5 7 对应为 v[v.size()-2]   v[v.size()-4]   v[v.size()-6] 

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

int main()
{
    int n=0;
    while(cin>>n)
    {
        long long  sum=0;
        vector<int>v;
        v.resize(3*n);
        for(int i =0; i<3*n;i++)
        {
            cin>>v[i];
        }
        sort(v.begin(), v.end());
        for(int i=0;i<n;i++)
        {
            sum+=v[v.size()-2*(i+1)];
        }
        cout<<sum<<endl;
    }
   
}


编辑于 2022-10-12 15:33:34 回复(0)
注意输入输出吧
#include<vector>
(721)#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
    long long  res=0,n;
    long long  temp;
    cin>>n;
    int a = 3*n;
    vector<long long> ve;
    while(a-- > 0)
    {
        cin>>temp;
        ve.push_back(temp);
    }
    sort(ve.begin(),ve.begin()+3*n,greater<int>());
    for(int i=1;i<=(2*n-1);i=i+2)
        res = res + ve[i];
    cout<<res;
}


发表于 2020-03-13 17:36:42 回复(0)
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 3e5 + 10;

int n, a[N];

int main()
{
    cin >> n;
    for(int i = 0; i < 3*n; i++)
        scanf("%d", &a[i]);
    sort(a, a + 3*n);

    long long ret = 0;
    for(int i = n; i < 3*n-1; i += 2)
        ret += a[i];
    cout << ret << endl;
    return 0;
}
发表于 2024-05-01 17:58:23 回复(1)
#include <iostream>
#include<algorithm>
using namespace std;
const int M=300003;
int n;
int a[M];
int main() {
    cin>>n;
    for(int i=0;i<3*n;i++)
      cin>>a[i];
    sort(a,a+3*n);
    long long ans=0;
    for(int i=3*n-2;i>=n;i-=2)
       ans+=a[i];
    cout<<ans<<endl;

    return 0;
}
// 64 位输出请用 printf(\"%lld\")

题目比较简单,不要想复杂就好
发表于 2024-01-21 22:20:27 回复(0)

分析:将所有数存入arr数组中,先将数组进行排序(从小到大),每次都取数组中最小的一个、最大的一个和次大的一个,这样可以保证每次分组中拿到最大的可能的数

import java.util.Arrays;
import java.util.Scanner;

public class demo1 {
    //组队竞赛
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        int[] arr = new int[3 * n];
        for(int i = 0; i < 3 * n; i++) {
            arr[i] = in.nextInt();
        }
        Arrays.sort(arr);
      // sum 的值可能会很大,所以用 Long 类型
        long sum = 0;

        for(int i = 0; i < n; i++) {
            sum += arr[arr.length - 2 * (i + 1)];
        }

        System.out.println(sum);
    }
}
编辑于 2023-11-28 18:55:38 回复(0)

组队竞赛

分析:将所有数存入arr数组中,竞赛时分组要使得所有组的中位数之和最大,可以先将数组进行排序(从小到大)
每次都取数组中最小的一个、最大的一个和次大的一个,这样可以保证每次分组中拿到最大的可能的数

方法一:

如:1 2 3 4 5 6 7 8 9
分组:189 267 345
则中位数最大和为 8+6+4=18
计算这几个数的下标公式:arr.length() - 2 * (i + 1)

代码

import java.util.*;

public class Main{
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        //输入组数
        int n = sc.nextInt();
        //存储所有数据的数组
        int[] arr = new int[3 * n];
        //输入所有队员的水平值
        for(int i = 0; i < 3 * n; i++) {
            arr[i] = sc.nextInt();
        }
        //将数组进行排序
        Arrays.sort(arr);
        //存储最大水平和
        long sum = 0;
        //后 2/3 个数字的奇数位的和
        //根据公式计算最大水平和
        for(int i = 0; i < n; i++) {
            sum += arr[3 * n - 2 * (i + 1)];
        }
        //输出结果
        System.out.println(sum);
    }
}

方法二:

还有一种解法就是我没发现取的数就是排序后数组中后 2/3 的数据中从最小的一个开始依次跳一个的所有数之和
即:后 2/3 个数中所有位置为奇数的数
如:1 2 3 4 5 6 7 8 9
456789中:4+6+8=18

代码

import java.util.*;

public class Main{
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        //输入组数
        int n = sc.nextInt();
        //存储所有数据的数组
        int[] arr = new int[3 * n];
        //输入所有队员的水平值
        for(int i = 0; i < 3 * n; i++) {
            arr[i] = sc.nextInt();
        }
        //将数组进行排序
        Arrays.sort(arr);
        //存储最大水平和
        long sum = 0;
        //后 2/3 个数字的奇数位的和
        for (int i = n; i < 3 * n; i += 2) {
            sum += arr[i];
        }
        //输出结果
        System.out.println(sum);
    }
}
发表于 2023-07-16 13:18:25 回复(1)
#include <iostream>
#include<algorithm>
#include<stdio.h>
using namespace std;
bool com(int a, int b) {
    return a > b;
}/*降序快排因子*/

int main() {
    int a;/*组数*/
    cin >> a;
    int n = 3 * a;/*人数*/
    int b[n];
    int i = 0;
    while (i < n) {
        cin >> b[i++];
    }
/*降序*/
    sort(&b[0], &b[n], com);
    long  s = 0;/*必须用long 不然存不下这恶心的测试用例*/
    i = 0;
    while (i < a) {
        s = s + b[(2 * i++) + 1];
    }/*将降序数组的第1 3 5 7 9 ...元素求和,一共a组是中间数*/
    cout << s;
}
发表于 2023-05-08 10:47:53 回复(0)
import java.util.*;
public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        List<Integer> avgs = new ArrayList<>();
        for(int i = 0; i < 3 * n; i++) {
            avgs.add(sc.nextInt());
        }
        System.out.println(findMax(n, avgs));
    }
    private static long findMax(int n, List<Integer> avgs) {
        Collections.sort(avgs, (a1, a2) -> a2 - a1 );
        long res = 0;  // 注意类型为 long,测试用例会超过整型的取值范围
        for(int i = 0; i < n; i++ ) {
            res += avgs.get(i * 2 + 1);
        }
        return res;
    }
}
发表于 2022-01-28 09:43:24 回复(0)
import java.util.*;
 public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int i;
        long sum = 0;
        int n = sc.nextInt();
        int[] array = new int[3*n];
        for(i = 0; i < array.length; i++){
            array[i] = sc.nextInt();
        }
        Arrays.sort(array);
        for(i = 0; i < n; i++){
            sum += array[array.length-2*(i+1)];
        }
        System.out.println(sum);
    }
}
发表于 2022-01-20 17:10:42 回复(0)
如下
public class Main1 {
    //保证每组的第二个值取到能选择的最大值就可以,
    // 我们每次尽量取最大,但是最大的数不可能是中位数,
    // 所以退而求其次,取每组中第二大的
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNext()) {
            int n = scanner.nextInt();
            long[] array = new long[3 * n];
            for (int i = 0; i < (3 * n); i++) {
                array[i] = scanner.nextLong();
            }
            Arrays.sort(array);
            long sum = 0;
            for (int i = 0; i < n; i++) {
                sum += array[array.length - (2 * (i + 1))];
            }
            System.out.println(sum);
        }
    }
}

发表于 2022-01-16 22:51:53 回复(0)
#include<iostream>
#include<vector>
#include <algorithm> 
using namespace std;

int main()
{
    vector<int> v;
    long long nums;
    cin >> nums;
    v.reserve(3 * nums);
    for (size_t i = 0; i < 3 * nums; ++i)
    {
        int t;
        cin >> t;
        v.push_back(t);
    }
    sort(v.begin(), v.end());//排序
    long long tmp = 0, j = 0;
    for (int i = (3 * nums) - 2; i >= 0; i -= 2) //1 2 5 5 7 8,每次取 7 5 即可
    {
        if (j < nums)
        {
            tmp += v[i];
            ++j;
        }
        else
            break;
    }
    cout << tmp << endl;
    return 0;
}

发表于 2020-05-31 21:39:45 回复(0)

贪心算法

既然不能选最大,我们就选第二大,将数组排个序,然后获取下标为 n, n+2, n+4,...,3n-2 的元素并求和好了
这样就获取到所有队伍的水平值总和最大值.

也可以这么理解
我们看测试用例
5 2 8 5 1 5
我们将其排序
1 2 5 5 5 8
不妨令 1 5 5 为一个组合
2 5 8 作为另一个组合
为什么要这么划分呢?
既然队伍的平均水平是队伍里第二水平的和
这样的话,我们让队伍的最小的元素就取排序后数组中的前n-1(数组下标从0开始)个元素好了
接下来的问题就是剩下的2n个元素怎么划分的问题了,我们假设这样分:
从n-2n-1的作为队伍的第二,但是这样一来,我们得到的和一定不是最大值,我们这样考虑,假如,n和n+1一组,n+2和n+3一组,这样每组的第二分别是 n, n+2, n+4,...,3n-2,显然n+1 < n+2, n+2 < n+4, n+3 < n+6, 2n < 3n-2.
这就是我们要的最大的结果呀

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>

#define DEBUG 0

int main(void)
{
    std::vector<int> array(300003, 0);
    int n = 0;
    int i = 0;
    long long sum = 0;
    while((std::cin >> n) && ((n >= 1) && (n <= 100000)))
    {
#if DEBUG
        std::cout << "[DEBUG] n = " << n << std::endl;
#endif
        for(i = 0; i < 3*n; ++i)
        {
            std::cin >> array[i];
        }
#if DEBUG
        std::cout << "[DEBUG] before sort, array = ";
        for(i = 0; i < 3*n; ++i)
        {
            std::cout << array[i] << " ";
        }
        std::cout << std::endl;
#endif

        std::sort(array.begin(), array.begin() + 3*n);

#if DEBUG
        std::cout << "[DEBUG] after sort, array = ";
        for(i = 0; i < 3*n; ++i)
        {
            std::cout << array[i] << " ";
        }
        std::cout << std::endl;
#endif
        for(i = n; i <= 3*n -2; i = i+2)
        {
#if DEBUG 
            std::cout << "[DEBUG] array[" << i << "] = " << array[i] << std::endl;
#endif
            sum += array[i];
        }

        std::cout << sum << std::endl;
        sum = 0;
        array.clear();
#if DEBUG
        std::cout << "[DEBUG] array.capacity() = " << array.capacity() << std::endl;
#endif
    }

    return 0;
}
编辑于 2019-05-20 20:36:44 回复(0)

问题信息

上传者:小小
难度:
13条回答 5836浏览

热门推荐

通过挑战的用户