1068 分数线的划定

该博客讨论了一种考试中确定面试分数线的方法,即基于计划录取人数的150%来划定分数线。博主指出,这个过程并不复杂,主要涉及对笔试成绩的排序和筛选。程序示例展示了如何找出所有达到面试分数线的选手的报名号和笔试成绩。

1068 分数线的划定

模拟,搜索,这就是橙题的水平,真的不难
则面试分数线为排名第m*150%(向下取整)名的选手的分数,而最终进入面试的选手为笔试成绩不低于面试分数线的所有选手
一个考试,有笔试成绩,如果达到了面试的成绩那么就可以进行面试,但是面试的分数线不确定,面试分数线根据计划录取人数的150% 划定,即如果计划录取m名志愿者,所以最终进入面试的人,笔试成绩不能低于面试分数线
所以说这个题为什么还要搞这么多的花花蛾子
输出所有进入面试的选手的报名号和笔试成绩,自己弄程序编

#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<string>
#include<cstring>
using namespace std;
int s[105],k[10005][105];
int main()
{
    int n,m,ss,kk,count=0,i,max=0,x,j;
    scanf("%d%d",&n,&m);//输入人数和支援人数 
    m=m*1.5;//处理录取的人数 
    for(i=0;i<n;i++)
    {
        scanf("%d%d",&kk,&ss);//输入编号和成绩	 
        k[kk][ss]++;//记录编号,表示有人,类似桶排 
        s[ss]++;//记录这个分数的人数,防止重复 
    }
    for(i=100;count<m;i--)//动态条件 
        count+=s[i];//类似桶,表示录取的人数 
    printf("%d %d\n",i+1,count);
    x=i+1;//人数 
    for(i=100;i>=x;i--)
        for(j=1000;j<=10000;j++)//所有可能的分数 
            if(k[j][i]) printf("%d %d\n",j,i);
    return 0;
}
<think>好的,我现在要解决用户的问题,关于NOIP 2009普及组P1068题目分数线划定的C语言实现。首先,我需要仔细理解题目的要求,确保自己正确把握每一个细节。 题目大意是说,根据面试分数和笔试分数之和来确定进入面试的选手,然后根据计划录取人数的150%划定分数线。分数相同的选手需要全部进入,即使超过150%。同时,输出分数线和实际进入面试的人数。嗯,这里的关键点有几个:排序规则、分数线计算、以及如何处理同分的情况。 首先,我需要明确排序规则。题目要求按总分从高到低排序,总分相同则按笔试成绩从高到低,如果笔试成绩也相同,可能需要保持原顺序或者看其他条件?但题目描述中没有提到这种情况的处理,所以可能不需要特别处理,只要满足前两个条件即可。比如,总分相同,笔试成绩高的排前面;如果总分和笔试都相同,可能按报名号排序?或者题目数据中没有这种情况,所以不需要处理?这点可能需要看题目具体要求,但根据常规处理,如果前两个条件相同,可能需要按报名号升序排列?不过原题描述可能没有这个要求,用户提供的引用里提到P1068属于分数线划定,可能实际处理中总分和笔试成绩相同的视为同分,都录取。 接下来,分数线划定的步骤。首先,计算进入面试的人数m,是计划人数乘以150%后向下取整。然后,找到排名第m位的选手的总分作为分数线。但所有总分等于分数线的选手都需要被录取,即使超出m的数量。因此,实际录取人数可能大于等于m。 然后,数据结构方面,每个选手的信息包括报名号、笔试成绩、面试成绩和总分。需要定义一个结构体来存储这些信息,然后进行排序。 接下来,具体步骤: 1. 输入n和m,其中m是计划录取人数。 2. 计算进入面试的人数threshold = floor(m * 1.5)。注意这里可能要用整数运算,比如m乘以3再除以2,或者用浮点计算后取整。不过要注意,比如当m=4时,1.5倍是6,所以正确的方式是m*3/2吗?或者用ceil?需要确认题目中的描述。题目中描述的是“计划录取人数的150%”,即向下取整。比如,样例输入中的情况是6人,计划录取人数是5,所以5*1.5=7.5,向下取整是7,所以threshold=7。那么正确的计算方式应该是m * 3 / 2吗?例如,用整数运算的话,可以用(m*3 +1)//2 来四舍五入?或者题目中的样例可能采用直接截断小数的方式。根据题目样例输入中的情况,比如原题样例输入为: 比如,样例输入可能为: 6 3 1000 90 80 1001 85 85 1002 90 78 1003 90 88 1004 80 90 1005 85 80 计划录取人数3,则3*1.5=4.5,取整后是4,所以前4名的总分确定分数线,但如果有同分,可能实际人数更多。 回到问题,正确的threshold计算应为floor(m * 1.5),即取整数部分。例如,在C语言中,可以写成threshold = (m * 3) / 2,因为1.5等于3/2,整数运算会自动截断小数部分。例如,当m=5时,5*3=15,除以2得7.5,整数部分是7,这样得到正确的threshold=7。因此,正确的计算方式是用m乘以3再除以2,得到整数部分。 接下来,需要将所有选手按总分从高到低排序,总分相同则按笔试成绩从高到低排序,如果都相同,可能需要按报名号升序排列?或者原题是否允许这种情况?根据常规处理,可能题目数据中不会有总分和笔试都相同的,但代码中必须处理这种情况。所以,在排序的比较函数中,需要先比较总分,总分相同则比较笔试成绩,如果笔试也相同,可能需要按报名号从小到大排列?或者题目没有说明,但根据通常的竞赛题,可能不需要处理,或者可能按报名号的升序排列?例如,原题中的样例可能需要这样的处理。 假设结构体定义如下: typedef struct { int id; int written; int interview; int total; } Candidate; 然后,比较函数应该按照总分降序,总分相同则笔试成绩降序。如果笔试成绩也相同,可能需要按报名号升序排列?或者不处理?需要根据题目要求。但题目描述中没有提到这种情况,所以可能在代码中不需要处理,或者按报名号升序排列以保持稳定。这里需要确认原题的情况。例如,在样例输入中,如果有两个总分和笔试成绩相同的选手,他们的相对顺序可能影响是否被录取。但根据题目要求,只要总分相同,即使超过threshold,也要全部录取,所以比较函数中的第三条件可能不影响最终结果,但为了排序稳定,可能需要按报名号升序排列,这样在总分和笔试相同的情况下,报名号小的排在前面。 所以,在排序的比较函数中,当总分和笔试成绩都相同时,按报名号从小到大排序。或者,可能不需要,但为了确定性,最好加上这个条件。 接下来,排序后的threshold位(索引为threshold-1)的总分即为分数线。然后,需要统计所有总分大于等于该分数线的选手的数量。这可能包括更多选手,如果第threshold位之后的选手的总分等于该分数的话。 例如,假设排序后的数组如下: 索引0: 总分200,笔试100 索引1: 总分190,笔试95 ... 索引threshold-1: 总分180,笔试90 索引threshold: 总分180,笔试90 索引threshold+1: 总分180,笔试85 那么分数线是180,所有总分>=180的选手都要被录取,所以实际人数是threshold+2? 因此,在代码中需要找到分数线score_line = candidates[threshold-1].total,然后遍历所有候选人,统计total >= score_line的数量。 接下来,代码的大致步骤: 1. 读取n和m。 2. 计算threshold = (m * 3) / 2。注意这里是否需要考虑m为奇数的情况?比如当m=5时,5*1.5=7.5,取整是7,所以用整数运算是对的。 3. 读取n个候选人的信息,计算总分。 4. 对候选人数组进行排序,排序规则是总分降序,笔试降序,报名号升序。 5. 确定分数线score_line = candidates[threshold-1].total。 6. 遍历数组,统计所有total >= score_line的人数。 7. 输出score_line和实际人数,然后输出这些人的报名号和成绩。 但需要注意,如果threshold大于n的情况?例如,当n小于threshold时,比如n=5,而threshold=7,这时候threshold-1=6,会导致数组越界。但根据题目描述,题目保证m <= n,所以threshold = floor(m*1.5),而m<=n,所以threshold可能大于n吗?比如,当m=1000,n=1000,那么threshold=1500,但此时n=1000,这时候threshold超过n,如何处理?根据题目描述,应该是这种情况不可能出现,因为m是计划录取的人数,不能超过n?或者题目可能保证输入的m满足threshold<=n? 根据题目实际情况,可能题目中的输入数据保证m的合理范围,例如,m<=n,且threshold不会超过n。或者,在代码中需要处理这种情况。例如,在threshold超过n时,取所有候选人。例如,当threshold大于n时,分数线是排序后的最后一个元素的总分,然后统计所有大于等于该分数的人。所以代码中应该处理这种情况,当threshold >=n时,threshold取n,然后分数线是最后一个元素的总分。比如,当n=5,m=5,threshold=7.5,取7,但n=5,这时候threshold是7,但数组只有5个元素,此时threshold-1=6,超出数组范围。这时需要将threshold调整为n的最小值,即threshold = min(threshold, n)。所以在代码中,在计算threshold之后,需要判断是否超过n,如果超过,则调整为n。例如: threshold = m * 3 / 2; if (threshold > n) { threshold = n; } 或者,例如,当threshold超过n时,直接取所有候选人,然后分数线是最后一位的总分。例如,假设n=3,m=3,那么threshold=4.5,取4,但n=3,所以threshold会被调整为3。此时,分数线是第三位(索引2)的总分。然后统计所有>=该分的候选人。比如,如果有三个候选人,他们的总分分别是200,200,200,那么分数线是200,实际人数是3。但如果threshold是3,而n=3,那么取第三位,所有总分>=第三位的总分的都被录取,即全部3人。 所以,在代码中,应该先计算threshold = m*3/2,然后判断threshold是否超过n,如果超过,则设为n。或者,在计算threshold之后,在取第threshold-1位的时候,判断是否超过数组长度。例如,在排序后,实际的有效threshold是取threshold和n的较小值。这一步非常重要,否则会导致数组越界。 因此,正确的处理方式是: int threshold = (m * 3) / 2; // 计算计划数的150%,向下取整 if (threshold > n) { threshold = n; } 但这里可能不需要,因为题目中的m可能不会超过n。例如,题目中的输入保证m <= n。但为了代码的鲁棒性,最好加上这个判断。 接下来,编写代码的步骤: 在C语言中,需要处理结构体数组的排序。使用qsort函数,自定义比较函数。 比较函数的逻辑: 对于两个候选人a和b: 1. 比较总分:如果a.total > b.total,返回-1(降序)。 2. 如果总分相同,比较笔试成绩:a.written > b.written,返回-1。 3. 如果笔试成绩也相同,比较报名号:a.id < b.id,返回-1(升序)。 因此,比较函数可以这样写: int compare(const void *a, const void *b) { Candidate *c1 = (Candidate *)a; Candidate *c2 = (Candidate *)b; if (c1->total != c2->total) { return c2->total - c1->total; // 降序 } else if (c1->written != c2->written) { return c2->written - c1->written; // 笔试降序 } else { return c1->id - c2->id; // 报名号升序 } } 这样,当总分和笔试成绩都相同时,报名号小的排在前面。 然后,读取输入,处理每个候选人: 读取n和m,然后循环n次,读取每个的id,written,interview,计算total=written + interview。 存储到数组中,排序,然后处理threshold。 接下来,确定分数线。此时,如果threshold是0的话,比如当m=0时,但题目中m应该是正整数,所以无需处理。假设threshold >=1。 但需要注意,当threshold为0时的情况,例如当m=0,但题目中的输入可能保证m>=1? 根据题目描述,题目中的输入格式是怎样的?例如,原题P1068的描述中,输入第一行是两个整数n和m,表示总人数和计划录取人数。题目中是否保证m>=1?可能原题中的数据范围中m是正整数,所以threshold至少为1。因此,在代码中可以不处理threshold为0的情况。 例如,假设输入中的m是正整数,所以threshold至少是1。 然后,score_line = candidates[threshold-1].total。 然后,统计所有candidates[i].total >= score_line的数量。 例如,遍历整个数组,从0到n-1,如果当前元素的总分>=score_line,计数加一。一旦遇到总分小于score_line,可以终止循环,因为数组已排序,后面的元素总分更小。或者,因为可能有多个等于的情况,所以必须遍历整个数组直到末尾?比如,如果中间某个元素的总分等于score_line,但后续的元素总分可能也等于。所以必须遍历整个数组。 因此,正确的做法是遍历整个数组,统计所有total >= score_line的人数。 例如: int count = 0; int score_line = candidates[threshold-1].total; for (int i = 0; i < n; i++) { if (candidates[i].total >= score_line) { count++; } else { break; // 后面的总分更小,可以提前终止 } } 哦,这里有问题,因为数组是按降序排列的,所以一旦遇到一个元素的总分小于score_line,后面的所有元素的总分都更小,可以break。但如果是等于的情况,比如score_line是180,前面有多个180的,后面可能有更多?不,数组是按降序排列的,所以所有总分>=score_line的元素都排在前面。例如,所有总分等于score_line的元素在数组中应该位于threshold-1的位置或前面。那是否正确? 例如,假设threshold=5,那么第5个元素(索引4)的总分是score_line。那么在数组中,索引0到4的总分>=score_line。但可能存在索引4之后的元素的总分等于score_line吗?比如,总分可能相同,但笔试成绩较低,导致排序在后面。例如: 假设threshold=5,那么第5个元素(索引4)的总分是180,笔试成绩是90。后面的元素可能有总分180,但笔试成绩低于90,所以排序在后面。因此,他们的总分等于score_line,但笔试成绩低,所以总分相同的情况下,笔试成绩高的排在前面。因此,这些元素的总分等于score_line,但因为笔试成绩较低,所以排在后面。因此,他们的总分虽然等于score_line,但因为笔试成绩低,所以总分相同的情况下会被排在后面,因此他们的总分等于score_line,但可能不会被统计到count中。但根据题目要求,所有总分>=score_line的都应该被录取,不管笔试成绩如何。因此,上述方法中的遍历整个数组直到找到所有总分>=score_line的元素是错误的,因为后面的元素可能总分等于score_line,但笔试成绩低,所以被排在后面。 这会导致错误。例如,假设threshold=4,score_line=180,但数组中索引4的总分是180,笔试成绩是85,而索引5的总分也是180,但笔试成绩是80。此时,这两个人的总分都等于score_line,但由于笔试成绩低,排在后面。此时,根据题目要求,他们也应该被录取,因为总分>=score_line。因此,仅仅遍历到threshold是不够的,必须遍历整个数组,找出所有总分>=score_line的选手。或者,在排序之后,所有总分>=score_line的选手一定在数组的前面部分? 这显然不正确。例如,可能有一个人的总分等于score_line,但由于笔试成绩较低,所以在数组中的位置在threshold之后。比如,当threshold=5,数组的前5个元素的总分是score_line,但后面某个元素的总分也是score_line,但笔试成绩较低,所以排在后面。这时候,根据题目要求,这些后面的元素也应该被录取。 这说明,仅仅统计前threshold个元素是不够的,必须遍历整个数组,统计所有总分>=score_line的元素的数量。 因此,正确的做法是: 计算score_line后,遍历整个数组,统计所有total >= score_line的选手的数量。例如: int score_line = candidates[threshold-1].total; int count = 0; for (int i = 0; i < n; i++) { if (candidates[i].total >= score_line) { count++; } else { break; // 因为数组是降序排列,后面的元素total更小,不可能>=score_line } } 但是,这里是否有可能后面的元素的total等于score_line的情况?比如,当多个选手的总分等于score_line,但由于他们的笔试成绩不同,导致排序时可能分布在threshold-1的前后? 例如: 假设有6个选手,他们的总分分别为:200, 190, 180, 180, 180, 170。threshold是4(假设m=3,threshold=3*1.5=4.5取4)。那么score_line是candidates[3].total=180。此时,遍历数组时,前四个元素的总分>=180,而第五个元素的总分也是180,但由于笔试成绩可能比第三个或第四个低,导致排序在第四位之后。例如,假设第三个元素的总分180,笔试90;第四位总分180,笔试85;第五位总分180,笔试80。那么,在数组中,第五位的总分是180,但笔试成绩较低,所以排在第四位之后。这时,第五位的total等于score_line,所以应该被计入count。但是,上述循环中的代码在遇到第五位时会发现其total等于score_line,继续计数,直到遇到第一个total < score_line的元素才会break。所以,在这种情况下,循环中的count会正确统计所有total>=score_line的元素。 因此,正确的代码应该是遍历整个数组,但一旦发现某个元素的total < score_line,后面的元素都不满足条件,可以break。因为数组是按降序排列的,所以一旦出现一个元素的总分小于score_line,后续的总分只会更小。 但这里有个例外情况吗?比如,当数组中存在多个元素的总分等于score_line,但由于笔试成绩的不同,导致某些元素的总分等于score_line但排在后面? 例如,假设数组中的元素总分如下: 200, 190, 180, 180, 180, 170, 180(总分) 这种情况是否可能?不可能,因为排序是按照总分降序排列的。如果有后面的元素的总分为180,它们会被排在前面,因为总分相同的情况下,笔试成绩高的排在前面。例如,假设最后一个元素的总分是180,笔试成绩是95,那么它会被插入到总分180且笔试成绩较高的位置,例如排在第三或第四的位置。因此,数组中的总分是按降序排列的,所以所有总分等于score_line的元素都位于threshold-1的位置或之前,或者在之后的位置吗? 这似乎矛盾。假设threshold是4,score_line是180,数组中前四个元素的总分都是>=180。此时,第五位元素的总分可能等于180吗? 例如,假设四个元素的总分是200, 190, 180, 180(threshold=4,所以score_line=180)。第五位元素的总分是180,笔试成绩比第四个低,所以排在第四位之后。那么,第五位元素的总分等于score_line,应该被计入。 这时候,按照循环中的代码,当遍历到第五位时,total等于score_line,count++,继续循环。直到第六位元素的总分170时,才break。这样,所有总分>=180的元素都被计数。 这说明,必须遍历整个数组,直到遇到第一个total < score_line的元素,才能停止。否则,会漏掉后面总分等于score_line的元素? 但根据排序规则,所有总分相同的元素会被排在前面吗?例如,总分相同的元素,按笔试成绩降序排列。假设有一个元素总分等于score_line,但笔试成绩比threshold-1位置的元素低,那么它会被排在后面? 例如,threshold-1位置的总分是180,笔试成绩是80。而后面有一个元素的总分是180,笔试成绩是70,则它会被排在后面。此时,这个元素的总分等于score_line,所以应该被计入count。所以在循环中必须继续遍历到该元素。 因此,循环中的条件必须遍历整个数组,或者直到遇到第一个total < score_line的元素为止。因为数组是降序排列的,一旦出现一个total < score_line的元素,后面的所有元素的总分都更小,所以可以break。 因此,正确的代码应该遍历整个数组,直到遇到第一个total < score_line的元素,然后break。但是,在这种情况下,后面的元素可能还有total等于score_line的吗? 不可能,因为数组是降序排列的。例如,如果数组中有一个元素的总分等于score_line,但笔试成绩较低,那么它会被排在总分等于score_line但笔试成绩较高的元素之后,但所有总分等于score_line的元素会被排在一起吗?不一定。例如: 总分排序:200, 190, 180(笔试90),180(笔试85),180(笔试80),170. 此时,threshold=4,score_line=180(第四个元素的总分是180,笔试85)。第五个元素的总分是180,笔试80,所以排在第四位之后。但在遍历数组时,第五个元素的total等于score_line,应被计入count。所以循环必须遍历到第五个元素,并继续检查第六个元素是否等于score_line? 根据排序规则,数组是按总分降序排列的,所以第五个元素的总分是180,符合条件,而第六个元素总分170,不满足条件。因此,循环中的代码应遍历到第五个元素,并计数。 这说明,正确的做法是遍历整个数组,但一旦发现某个元素的total < score_line,就break,否则继续计数。 所以,在代码中,循环应该这样写: count = 0; for (int i = 0; i < n; i++) { if (candidates[i].total >= score_line) { count++; } else { break; } } 这样,当遇到第一个总分小于score_line的元素时,循环终止,后面的元素不需要检查。例如,在之前的例子中,第五个元素的总分是180,符合条件,会被计数。第六个元素总分170,触发break。所以count会正确统计前五个元素中的总分>=180的? 不,第六个元素是170,所以第五个元素的总分是180,会被计数,而第六个元素的总分170,触发break。所以循环会处理到第五个元素吗?是的。因为i从0到n-1,依次检查每个元素。当i=0到4时,总分都>=180,count累加到5。i=5时,检查元素的总分170,触发break,循环结束。所以count是5。但根据实际情况,第五个元素的总分是180,应该被计数。所以代码是正确的,因为当i=4时,元素的总分180,被计数。i=5时,元素的总分170,触发break。此时,count是5吗?假设数组中有五个元素的总分>=180,那么count=5? 或者,数组的元素是: 索引0:200 → count++ 索引1:190 → count++ 索引2:180 → count++ 索引3:180 → count++ 索引4:180 → count++ 索引5:170 → break → 总count是5。 这确实正确,因为前5个元素总分>=180,而索引4的总分是180。但根据之前的例子,当threshold=4时,score_line是索引3的总分180。那么,第五个元素(索引4)的总分是180,也会被计入count。所以代码是正确的。 这表明,循环中的代码是正确的,可以正确统计所有总分>=score_line的元素的数量,无论它们在数组中的位置如何,因为数组是按降序排列的,所以只要存在这样的元素,它们一定出现在数组的前面部分,直到第一个总分小于score_line的元素出现。 因此,这样的代码是正确的。 接下来,代码的结构: 读取n和m→计算threshold→读取n个候选人→计算总分→排序→确定score_line→统计count→输出score_line和count→输出前count个候选人的id和总分。 但要注意,当threshold超过n时,比如n=3,m=3,threshold=4.5→4,此时n=3,threshold会被调整为3,此时score_line是candidates[2].total。统计所有>=该分的人数。 例如,当所有三个候选人的总分都是100,那么count=3,输出score_line=100,count=3,并输出他们的id和成绩。 现在,编写具体的C语言代码。 首先,结构体定义: typedef struct { int id; int written; int interview; int total; } Candidate; 然后,比较函数: int compare(const void *a, const void *b) { Candidate *c1 = (Candidate *)a; Candidate *c2 = (Candidate *)b; if (c1->total != c2->total) { return c2->total - c1->total; // 降序 } else if (c1->written != c2->written) { return c2->written - c1->written; // 笔试降序 } else { return c1->id - c2->id; // 报名号升序 } } 主函数: #include <stdio.h> #include <stdlib.h> typedef struct { int id; int written; int interview; int total; } Candidate; int compare(const void *a, const void *b) { Candidate *c1 = (Candidate *)a; Candidate *c2 = (Candidate *)b; if (c1->total != c2->total) { return c2->total - c1->total; } else if (c1->written != c2->written) { return c2->written - c1->written; } else { return c1->id - c2->id; } } int main() { int n, m; scanf("%d %d", &n, &m); int threshold = (m * 3) / 2; // 处理threshold超过n的情况 if (threshold > n) { threshold = n; } Candidate *candidates = (Candidate *)malloc(n * sizeof(Candidate)); for (int i = 0; i < n; i++) { scanf("%d %d %d", &candidates[i].id, &candidates[i].written, &candidates[i].interview); candidates[i].total = candidates[i].written + candidates[i].interview; } qsort(candidates, n, sizeof(Candidate), compare); int score_line = candidates[threshold - 1].total; int count = 0; for (int i = 0; i < n; i++) { if (candidates[i].total >= score_line) { count++; } else { break; } } printf("%d %d\n", score_line, count); for (int i = 0; i < count; i++) { printf("%d %d\n", candidates[i].id, candidates[i].total); } free(candidates); return 0; } 测试样例是否符合? 例如,NOIP2009普及组P1068的样例输入: 假设样例输入为: 6 3 1000 90 80 1001 85 85 1002 90 78 1003 90 88 1004 80 90 1005 85 80 计划录取3人,threshold=3*1.5=4.5→4。所以threshold=4。 每个候选人的总分: 1000: 90+80=170 1001:85+85=170 1002:90+78=168 1003:90+88=178 1004:80+90=170 1005:85+80=165 Wait,这似乎与原题样例可能不同,或者我记错了。或者可能原题的样例输入不同? 假设原题样例输入为: 6 3 1000 90 60 → 150 1001 85 95 → 180 1002 90 90 → 180 1003 80 100 → 180 1004 85 80 → 165 1005 95 85 → 180 假设这样,那么总分排序后: 候选人按总分排序: 1003:80+100=180 → total=180,written=80 1001:85+95=180 → written=85 1002:90+90=180 → written=90 1005:95+85=180 → written=95 假设这些人的总分都是180,那么排序时,按笔试成绩降序排列。例如,1005的笔试成绩95最高,然后是1002的90,1001的85,1003的80。所以排序后的顺序是:1005,1002,1001,1003。其他候选人总分较低。 假设threshold=4,那么score_line是第四位(索引3)的总分,即180。然后统计所有总分>=180的人数。这里有四个候选人,他们的总分都是180。所以count=4。输出分数线180和人数4,然后输出这四个人的ID和总分。 但根据代码,score_line是180,count=4。 所以代码可以正确处理这种情况。 另一个测试情况是,当threshold超过n时。例如,n=3,m=3,threshold=4.5→4。但n=3,所以threshold调整为3。此时,第三位(索引2)的总分作为score_line。统计所有总分>=该分的人数。 总之,这段代码应该可以正确处理各种情况。 最后,用户要求用C语言实现,所以代码正确性很重要。需要确保排序规则正确,threshold计算正确,以及统计人数正确。</think>### NOIP2009普及组P1068分数线划定C语言实现 **题目要求** 根据选手的笔试和面试总分确定进入面试的分数线,按总分从高到低排序。若总分相同则按笔试成绩降序排列,若笔试成绩相同则按报名号升序排列。录取人数为计划录取人数的150%(向下取整),若最后一名有同分者则全部录取。 **实现步骤** 1. **数据结构定义** 使用结构体存储选手信息: ```c typedef struct { int id; // 报名号 int written; // 笔试成绩 int interview; // 面试成绩 int total; // 总分 } Candidate; ``` 2. **排序规则** 自定义比较函数: ```c int compare(const void *a, const void *b) { Candidate *c1 = (Candidate *)a; Candidate *c2 = (Candidate *)b; if (c1->total != c2->total) // 总分降序 return c2->total - c1->total; else if (c1->written != c2->written) // 笔试降序 return c2->written - c1->written; else // 报名号升序 return c1->id - c2->id; } ``` 3. **核心逻辑** ```c #include <stdio.h> #include <stdlib.h> int main() { int n, m; scanf("%d %d", &n, &m); int threshold = (m * 3) / 2; // 计算150%向下取整 if (threshold > n) threshold = n; // 处理超出人数的情况 Candidate *candidates = (Candidate *)malloc(n * sizeof(Candidate)); for (int i = 0; i < n; i++) { scanf("%d %d %d", &candidates[i].id, &candidates[i].written, &candidates[i].interview); candidates[i].total = candidates[i].written + candidates[i].interview; } qsort(candidates, n, sizeof(Candidate), compare); // 排序 int score_line = candidates[threshold - 1].total; int count = 0; for (int i = 0; i < n; i++) { if (candidates[i].total >= score_line) count++; else break; // 后续分数更小,提前终止 } printf("%d %d\n", score_line, count); for (int i = 0; i < count; i++) printf("%d %d\n", candidates[i].id, candidates[i].total); free(candidates); return 0; } ``` **示例说明** - **输入** ``` 6 3 1000 90 60 1001 85 95 1002 90 90 1003 80 100 1004 85 80 1005 95 85 ``` - **输出** ``` 180 4 1005 180 1002 180 1001 180 1003 180 ``` **注意事项** 1. 当计划录取人数的150%超过实际人数时,按实际人数计算。 2. 同分者按笔试成绩和报名号排序,确保结果唯一性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值