[CSP-S 2025] 社团招新题解

P14361 [CSP-S 2025] 社团招新 / club(民间数据)

题目背景

民间数据测试强度可能偏弱。

题目描述

小 L 是学校算法协会的成员。在今年的学校社团招新中,小 L 一共招收了 nnn 个新成员,其中 nnn偶数。现在小 L 希望将他们分到协会不同的部门。

算法协会共设有三个部门,其中第 iii (1≤i≤n1 \leq i \leq n1in) 个新成员对第 jjj (1≤j≤31 \leq j \leq 31j3) 个部门的满意度为 ai,ja_{i,j}ai,j。定义一个分配方案的满意度为所有新成员对分配到的部门的满意度之和,也就是说,若将第 iii (1≤i≤n1 \leq i \leq n1in) 个新成员分配到了第 di∈{1,2,3}d_i \in \{1,2,3\}di{1,2,3} 个部门,则该分配方案的满意度为 ∑i=1nai,di\sum_{i=1}^{n} a_{i,d_i}i=1nai,di

小 L 不希望某一个部门的新成员数量过多。具体地,他要求在分配方案中,不存在一个部门被分配多于 n2\frac{n}{2}2n 个新成员。你需要帮助小 L 求出,满足他要求的分配方案的满意度的最大值。

输入格式

本题包含多组测试数据。

输入的第一行包含一个正整数 ttt,表示测试数据组数。

接下来依次输入每组测试数据,对于每组测试数据:

  • 第一行包含一个正整数 nnn,表示新成员的数量。
  • i+1i+1i+1 (1≤i≤n1 \leq i \leq n1in) 行包含三个非负整数 ai,1,ai,2,ai,3a_{i,1}, a_{i,2}, a_{i,3}ai,1,ai,2,ai,3,分别表示第 iii 个新成员对第 1,2,31,2,31,2,3 个部门的满意度。

输出格式

对于每组测试数据,输出一行一个非负整数,表示满足小 L 要求的分配方案的满意度的最大值。

输入输出样例 #1

输入 #1

3
4
4 2 1
3 2 4
5 3 4
3 5 1
4
0 1 0
0 1 0
0 2 0
0 2 0
2
10 9 8
4 0 0

输出 #1

18
4
13

说明/提示

【样例 1 解释】

该样例共包含三组测试数据。

对于第一组测试数据,可以将四个新成员分别分配到第 1,3,1,21,3,1,21,3,1,2 个部门,则三个部门的新成员数量分别为 2,1,12,1,12,1,1,均不超过 42=2\frac{4}{2} = 224=2,满意度为 4+4+5+5=184 + 4 + 5 + 5 = 184+4+5+5=18

对于第二组测试数据,可以将四个新成员分别分配到第 1,1,2,21,1,2,21,1,2,2 个部门,则三个部门的新成员数量分别为 2,2,02,2,02,2,0,均不超过 42=2\frac{4}{2} = 224=2,满意度为 0+0+2+2=40 + 0 + 2 + 2 = 40+0+2+2=4

对于第三组测试数据,可以将两个新成员分别分配到第 2,12,12,1 个部门,则三个部门的新成员数量分别为 1,1,01,1,01,1,0,均不超过 22=1\frac{2}{2} = 122=1,满意度为 9+4=139 + 4 = 139+4=13

【样例 2】

见选手目录下的 club/club2.in\textbf{\textit{club/club2.in}}club/club2.inclub/club2.ans\textbf{\textit{club/club2.ans}}club/club2.ans

该样例满足测试点 3,43,43,4 的约束条件。

【样例 3】

见选手目录下的 club/club3.in\textbf{\textit{club/club3.in}}club/club3.inclub/club3.ans\textbf{\textit{club/club3.ans}}club/club3.ans

该样例满足测试点 5∼85 \sim 858 的约束条件。

【样例 4】

见选手目录下的 club/club4.in\textbf{\textit{club/club4.in}}club/club4.inclub/club4.ans\textbf{\textit{club/club4.ans}}club/club4.ans

该样例满足测试点 999 的约束条件。

【样例 5】

见选手目录下的 club/club5.in\textbf{\textit{club/club5.in}}club/club5.inclub/club5.ans\textbf{\textit{club/club5.ans}}club/club5.ans

该样例满足测试点 15,1615,1615,16 的约束条件。

【数据范围】

对于所有测试数据,保证:

  • 1≤t≤51 \leq t \leq 51t5;
  • 2≤n≤1052 \leq n \leq 10^52n105,且 nnn 为偶数;
  • 对于所有 1≤i≤n1 \leq i \leq n1in1≤j≤31 \leq j \leq 31j3,均有 0≤ai,j≤2×1040 \leq a_{i,j} \leq 2 \times 10^40ai,j2×104

::cute-table{tuack}

测试点编号n=n=n=特殊性质
111222
222444^
3,43, 43,4101010^
5∼85 \sim 858303030^
999200200200B
10,1110, 1110,11^
12121210510^5105A
13,1413, 1413,14^B
15,1615, 1615,16^C
17∼2017 \sim 201720^

特殊性质 A:对于所有 1≤i≤n1 \leq i \leq n1in,均有 ai,2=ai,3=0a_{i,2} = a_{i,3} = 0ai,2=ai,3=0

特殊性质 B:对于所有 1≤i≤n1 \leq i \leq n1in,均有 ai,3=0a_{i,3} = 0ai,3=0

特殊性质 C:对于所有 1≤i≤n1 \leq i \leq n1in1≤j≤31 \leq j \leq 31j3ai,ja_{i,j}ai,j 均在 [0,2×104][0, 2 \times 10^4][0,2×104] 中独立均匀随机生成。

思路

首先,想到暴力枚举,显然只有20分。
随后,可以发现,该题能用贪心解决,首先贪心取最优,若超限,则直接贪心分割代价最小的几个即可。

代码见下

#include<bits/stdc++.h>
using namespace std;
long long t,n,a[100005][4],b[100005],op=0,c[4],d[100005],sd=0;
int main(){
	cin>>t;
    while(t--){
        cin>>n;
        op=0;
        c[1]=c[2]=c[3]=0;
        for(int i=1;i<=n;i++){
            cin>>a[i][1]>>a[i][2]>>a[i][3];
            if(a[i][1]>=a[i][2]&&a[i][1]>=a[i][3]){
                op+=a[i][1];
                b[i]=1;
                c[1]++;
            }
            else if(a[i][2]>=a[i][1]&&a[i][2]>=a[i][3]){
                op+=a[i][2];
                b[i]=2;
                c[2]++;
            }
            else{
                op+=a[i][3];
                b[i]=3;
                c[3]++;                
            }
        }
        sd=0;
        if(c[1]>=n/2+1){
            for(int i=1;i<=n;i++){
                if(b[i]==1){
                    d[++sd]=a[i][1]-max(a[i][2],a[i][3]);
                }
            }
            sort(d+1,d+sd+1);
            for(int i=1;i<=sd-n/2;i++){
                op-=d[i];
            }
            cout<<op<<endl;
        }
        else if(c[2]>=n/2+1){
            for(int i=1;i<=n;i++){
                if(b[i]==2){
                    d[++sd]=a[i][2]-max(a[i][1],a[i][3]);
                }
            }
            sort(d+1,d+sd+1);
            for(int i=1;i<=sd-n/2;i++){
                op-=d[i];
            }
            cout<<op<<endl;            
        }
        else if(c[3]>=n/2+1){
            for(int i=1;i<=n;i++){
                if(b[i]==3){
                    d[++sd]=a[i][3]-max(a[i][1],a[i][2]);
                }
            }
            sort(d+1,d+sd+1);
            for(int i=1;i<=sd-n/2;i++){
                op-=d[i];
            }
            cout<<op<<endl;            
        }
        else{
            cout<<op<<endl;
        }
    }
	return 0;
}
posted @ 2025-11-03 21:21  bz02_2023f2  阅读(30)  评论(0)    收藏  举报  来源