刷题Day8多属性排序

博客介绍了作者在大一时解决NOIP2009普及组分数线划定问题的经历,通过归并排序算法对包含成绩和报名号的志愿者数据进行排序,并根据规则确定面试入围者。文章强调了在排序过程中处理相等分数时需考虑报名号的细节,以及结构体在存储数组元素时的便利性。最终给出了AC代码示例。
摘要由CSDN通过智能技术生成

前言

 这题是我大一就做过的,奈何自己当时水平太低结果当时就只拿了10分;现在大三20minAC,感觉还是有点进步的哈哈哈…
题目链接地址:P1068 [NOIP2009 普及组] 分数线划定
在这里插入图片描述
在这里插入图片描述
解题思路:
 题目初看一大串文字表述很复杂,其实并不复杂。这道题要做的人物就是先把n个志愿者的成绩按照它已经指定好的方式排序,然后将录取人数*1.5利用向下取整(对应在C语言里是直接进行强制类型转换),在排好序的数组上找相应位置那个志愿者的分,然后看是否有同分情况有就顺延然后确定正式进入面试的人数,然后再按照被确定入围的面试者在数组对应的位置依次从大到小输出相应报名号和他的成绩即可。
 因此,预排序成为了一个必不可少的动作,但是这里的预排序和普通题目下的预排序不同之处在于这里比较的指标除了分数之外还有报名号。因此,在利用相应排序模板的时候,一定要注意,例如,我使用的归并排序,将相等的情况单独处理。归并排序设计到一个分治法的思想,当在进行最小归并的时候当分数相等的时候要注意按照报名号进行有限归入数组的操作;这样递归返回的时候可以保证局部顺序的正确性从而保证全局的正确性。
 因为本题属于多依据的排序,所以对于数组元素,在C语言里还是用结构体来存储比较方便。最后还是给出我的AC代码:

#include <stdio.h>
#include <stdlib.h>
struct node{
	int No;
	int score;
};
void Merge(int left,int mid,int right,struct node a[],struct node b[]){
	int i,j,k;
	for(i=left;i<=right;i++)
	   b[i]=a[i];
	i=left;
	j=mid+1;
	k=left;
	while(i<=mid&&j<=right){
		if(b[i].score>b[j].score){
			a[k]=b[i];
			k++;
			i++;
		}else if(b[j].score>b[i].score){
			a[k]=b[j];
			k++;
			j++;
		}else{
			if(b[i].No<b[j].No){
				a[k]=b[i];
				k++;
				i++;
			}else{
				a[k]=b[j];
				k++;
				j++;
			}
		}
	}
	while(i<=mid){
		a[k]=b[i];
		i++;
		k++;
	}
	while(j<=right){
		a[k]=b[j];
		k++;
		j++;
	}
	
	
	return;
	
	
}



void Mergesort(int left,int right,struct node a[],struct node b[]){
	if(left>=right)
	   return;
	int mid=(left+right)/2;
	Mergesort(left,mid,a,b);
	Mergesort(mid+1,right,a,b);
	Merge(left,mid,right,a,b);
	
	
	
	return;
}

int main(int argc, char *argv[]) {
	int n,m,i,ceil;

	scanf("%d%d",&n,&m);
	ceil=(int)(1.5*m);
	struct node racer[n],b[n];
	for(i=0;i<n;i++)
	  scanf("%d%d",&racer[i].No,&racer[i].score);
	Mergesort(0,n-1,racer,b);
	printf("%d ",racer[ceil-1].score);
	while(1){
		if(racer[ceil-1].score==racer[ceil].score)
		  ceil++;
		else
		  break;
	}

	printf("%d\n",ceil);
	for(i=0;i<ceil;i++){
		printf("%d %d\n",racer[i].No,racer[i].score);
	}
	
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值