前言
此题很水。先放链接:P1093 [NOIP2007 普及组] 奖学金
题目内容如下:
这题很水,因为输入规模小,思路还简单。
我的解题思路:
因为是多属性的排序,即需要从总分,单科以及学号三个角度进行排序,所以如果像我一样用C语言刷题的话,这里需要用到结构体来存这三个信息。然后由于只需要前五个同学的学号和总分情况,而不必关心其余的同学是什么样的。因此,如果用谋者排序模板全都排出来然后截取前五个,个人感觉有点大材小用而且也浪费了时间。所以在这里我借助冒泡排序的思想来解决这道题目。即每趟排序按总分,语文,学号的比较次序依次比较并将符合条件的结构体浮到数组最顶端,执行五次,则数组最后的五项逆序输出就是答案了。这样的话时间复杂度也就是O(n),比进行完整的排序(基于比较的排序最优时间复杂度是O(nlogn)好一点吧。
下面给出我的AC代码。
#include <stdio.h>
#include <stdlib.h>
struct node{
int No;
int Chinese;
int Maths;
int English;
int total;
};
int main(int argc, char *argv[]) {
int n,i;
scanf("%d",&n);
struct node student[n];
for(i=0;i<n;i++){
scanf("%d%d%d",&student[i].Chinese,&student[i].Maths,&student[i].English);
student[i].total=student[i].Chinese+student[i].Maths+student[i].English;
student[i].No=i+1;
}
int j;
struct node temp;
for(j=1;j<=5;j++){ //j表示选5次
for(i=0;i<n-j;i++){
if(student[i].total>student[i+1].total){
temp=student[i+1];
student[i+1]=student[i];
student[i]=temp;
}else if(student[i].total==student[i+1].total){
if(student[i].Chinese>student[i+1].Chinese){
temp=student[i+1];
student[i+1]=student[i];
student[i]=temp;
}else if(student[i].Chinese==student[i+1].Chinese){
if(student[i].No<student[i+1].No){
temp=student[i+1];
student[i+1]=student[i];
student[i]=temp;
}
}
}
}
}
for(j=1;j<=5;j++){
if(n-j>=0){
printf("%d %d\n",student[n-j].No,student[n-j].total);
}
}
return 0;
}