甲级PAT 1025 PAT Ranking(排序,成绩排序模拟)

1025 PAT Ranking(25 分)

Programming Ability Test (PAT) is organized by the College of Computer Science and Technology of Zhejiang University. Each test is supposed to run simultaneously in several places, and the ranklists will be merged immediately after the test. Now it is your job to write a program to correctly merge all the ranklists and generate the final rank.

Input Specification:

Each input file contains one test case. For each case, the first line contains a positive number N (≤100), the number of test locations. Then N ranklists follow, each starts with a line containing a positive integer K (≤300), the number of testees, and then K lines containing the registration number (a 13-digit number) and the total score of each testee. All the numbers in a line are separated by a space.

Output Specification:

For each test case, first print in one line the total number of testees. Then print the final ranklist in the following format:

registration_number final_rank location_number local_rank

The locations are numbered from 1 to N. The output must be sorted in nondecreasing order of the final ranks. The testees with the same score must have the same rank, and the output must be sorted in nondecreasing order of their registration numbers.

Sample Input:

2
5
1234567890001 95
1234567890005 100
1234567890003 95
1234567890002 77
1234567890004 85
4
1234567890013 65
1234567890011 25
1234567890014 100
1234567890012 85

Sample Output:

9
1234567890005 1 1 1
1234567890014 1 2 1
1234567890001 3 1 2
1234567890003 3 1 2
1234567890004 5 1 4
1234567890012 5 2 2
1234567890002 7 1 5
1234567890013 8 2 3
1234567890011 9 2 4

题目要求: 

这是一道模拟题,以期末考试为例,学生所在班级有一个排名,整个专业的所有学生又有一个排名,而你需要做的就是根据各班级中每位同学的分数给出每位学生的全专业排名以及所在班级号和班级排名。要注意排名是1 1 3这样而不是1 1 2。最后的结果按专业排名,专业排名相同按序号的字典序排序。

解题思路:

模拟题通常需要建立和题目要求一致的结构体。这里每位学生包含编号、成绩、专业排名、所在班级、班级排名。用一个一维数组学生表则可以表示所有的学生。

由于输入的时候是按班级顺序输入,所以对每个班级的学生进行局部成绩排序后直接给出他们的排名,这里只要控制在学生表排序的下标范围就可以了。按顺序存储到学生表中,从下标0开始存储,对于班级中的K各学生,加到班级最后一个同学的下标为L-1,那班级的第一个同学下标为L-K。从前往后给出排名。对每个班级都排好之后再对所有学生进行排序(也就是学生表下标0到下标l-1)按跟班级排名相同的方式给出排名。

注意:

1.注意对于成绩排序,比较当前学生和上一学生成绩是否相等,若相等,则跟上一学生排名相等,若不相等,则根据在班级中的位数加一。

2.按字典序排序可以用strcmp对字符数组按字典序排序

完整代码:

#include<bits/stdc++.h>
using namespace std;

struct Stu{
	char id[14];
	int score;
	int frank;
	int lnum; 
	int lrank;
};

Stu stu[30001];
int N,l=0;
bool cmp(Stu s1,Stu s2){
	if(s1.score > s2.score) return true;
	else if(s1.score == s2.score){
		if(strcmp(s1.id,s2.id)<0) return true;
		else return false;
	}else return false;
}

int main(){
	int i,j,K;
	scanf("%d",&N);
	for(i=1;i<=N;i++){
		scanf("%d",&K);
		for(j=0;j<K;j++){
			scanf("%s%d",&stu[l].id,&stu[l].score);
			stu[l].lnum = i;
			l++;
		}
		sort(stu+l-K,stu+l,cmp);
		for(j=l-K;j<l;j++){
			if(j==l-K){
				stu[j].lrank = 1;
			}
			else if(stu[j].score == stu[j-1].score){
				stu[j].lrank =stu[j-1].lrank;
			}
			else{
				stu[j].lrank =j-l+K+1;
			}
		}	
	}
	sort(stu,stu+l,cmp);
	for(j=0;j<l;j++){
		if(j==0){
			stu[j].frank = 1;
		}
		else if(stu[j].score == stu[j-1].score){
			stu[j].frank =stu[j-1].frank;
		}
		else{
			stu[j].frank =j+1;
		}
	}
	printf("%d\n",l);
	for(i=0;i<l;i++){
		if(i==l-1){
			printf("%s %d %d %d",stu[i].id,stu[i].frank,stu[i].lnum,stu[i].lrank);
		}else{
			printf("%s %d %d %d\n",stu[i].id,stu[i].frank,stu[i].lnum,stu[i].lrank);
		}
	}	
	return 0;
}

 后续:

这是算法笔记上的一道题目,然后看了下代码发现竟然和我写的差不多,开心,当时刚开始写的时候思路错的很离谱,打算用一个表存班级排名,一个表存专业排名,发现两个合不到一起,因为排序完就乱了,还得按编号查找,非常麻烦,然后就卡住了。后来想到了这种方法,总的用时差不多一个多小时。如果没有刚开始错误的思路应该会快点。果然思路还是很重要的。好的编程思路不仅减少代码量还能够更快速的解决问题。

然后发现我的代码比较写的有些冗长。这样就可以了。

bool cmp(Stu s1,Stu s2){
	if(s1.score > s2.score) return true;
	else return strcmp(s1.id,s2.id)<0;
}

代码简化

2019.2.8

由于使用了cin所以时间比之前要长

#include<bits/stdc++.h>
using namespace std;

struct Stu{
	string id;
	int grade,frank,lnum,lrank;
};
Stu stu[30010];
bool com(Stu s1,Stu s2){
	if(s1.grade!=s2.grade) return s1.grade>s2.grade;
	else return s1.id < s2.id; 
}

int main(){
	int n,k,i,j,start,num=0;
	cin>>n;
	for(i=1;i<=n;i++){
		start=num;
		cin>>k;
		for(j=1;j<=k;j++){
			cin>>stu[num].id>>stu[num].grade;
			stu[num++].lnum=i;
		}
		sort(stu+start,stu+num,com);
		stu[start].lrank=1;
		for(j=1;j<k;j++){
			if(stu[start+j].grade == stu[start+j-1].grade) stu[start+j].lrank=stu[start+j-1].lrank;
			else stu[start+j].lrank=j+1;
		}	
	}
	sort(stu,stu+num,com);
	stu[0].frank=1;
	for(i=1;i<num;i++){
		if(stu[i].grade==stu[i-1].grade) stu[i].frank=stu[i-1].frank;
		else stu[i].frank=i+1;
	}
	cout<<num<<endl;
	for(i=0;i<num;i++) cout<<stu[i].id<<" "<<stu[i].frank<<" "<<stu[i].lnum<<" "<<stu[i].lrank<<endl;
	return 0;
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值