PAT甲级-1075-PAT Judge(排序+疑难分析)

The ranklist of PAT is generated from the status list, which shows the scores of the submissions. This time you are supposed to generate the ranklist for PAT.

Input Specification:

Each input file contains one test case. For each case, the first line contains 3 positive integers, N (≤10​4​​ ), the total number of users, K (≤5), the total number of problems, and M (≤105), the total number of submissions. It is then assumed that the user id’s are 5-digit numbers from 00001 to N, and the problem id’s are from 1 to K. The next line contains K positive integers p[i] (i=1, …, K), where p[i] corresponds to the full mark of the i-th problem. Then M lines follow, each gives the information of a submission in the following format:

user_id problem_id partial_score_obtained

where partial_score_obtained is either −1 if the submission cannot even pass the compiler, or is an integer in the range [0, p[problem_id]]. All the numbers in a line are separated by a space.

Output Specification:

For each test case, you are supposed to output the ranklist in the following format:

rank user_id total_score s[1] ... s[K]

where rank is calculated according to the total_score, and all the users with the same total_score obtain the same rank; and s[i] is the partial score obtained for the i-th problem. If a user has never submitted a solution for a problem, then “-” must be printed at the corresponding position. If a user has submitted several solutions to solve one problem, then the highest score will be counted.

The ranklist must be printed in non-decreasing order of the ranks. For those who have the same rank, users must be sorted in nonincreasing order according to the number of perfectly solved problems. And if there is still a tie, then they must be printed in increasing order of their id’s. For those who has never submitted any solution that can pass the compiler, or has never submitted any solution, they must NOT be shown on the ranklist. It is guaranteed that at least one user can be shown on the ranklist.

Sample Input :
7 4 20
20 25 25 30
00002 2 12
00007 4 17
00005 1 19
00007 2 25
00005 1 20
00002 2 2
00005 1 15
00001 1 18
00004 3 25
00002 2 25
00005 3 22
00006 4 -1
00001 2 18
00002 1 20
00004 1 15
00002 4 18
00001 3 4
00001 4 2
00005 2 -1
00004 2 0

Sample Output :
1 00002 63 20 25 - 18
2 00005 42 20 0 22 -
2 00007 42 - 25 - 17
2 00001 42 18 18 4 2
5 00004 40 15 0 25 -

1、数据结构分析:

It is then assumed that the user id’s are 5-digit numbers from 00001 to N
这句话提示我们id号是从1-N的,因此可以用结构体数组下标来表示练习者的id号,这一点至关重要,它意味着有了每位练习者都有了一个key的地址映射,将一条提交记录匹配到练习者存储位置时,不再用遍历的方式,而直接通过key(id号)就找到了它对应的物理存储位置。换言之,是在逻辑记录与物理记录之间建立起了一一对应的关系

2、反向思维处理不显示情况:

反向想,只要有一道题分数不为-1,那么它就将显示在rankList上。设置一个标记变量isShown来标记是否显示即可。如果正向想,将会很复杂。

3、容易混淆的一点:

答案错误是0分,但未通过编译却是-1分,(为了与未提交区分,令最终未通过编译= -2分)二者是不一样的,比如说,如果都4道题未通过编译是不会显示在rankList上的,而4道题答案都错误,仍然是要出现在rankList上的。区分如下:

score = 0:答案错误
score = -1:未提交过
score = -2:未通过编译
  • 注意:

①由于v【0】中未存储信息,因此是从v.begin()+1开始sort的!!!

if(v[i].score[j] == full[j]) v[i].acCode++;必须要放在所有提交记录都输入以后!打擂完了才能确认满分题目个数!

if(mark != -1){
   v[id].isShown = true;
   v[id].score[pid] = max(mark, v[id].score[pid]); 
}else {
   v[id].score[pid] = -2;
}
if(mark != -1){
   v[id].isShown = true;
   v[id].score[pid] = max(mark, v[id].score[pid]); 
}else if(v[id].score[pid] == -1){
   v[id].score[pid] = -2;
}

比较以上两种写法,会发现第二种考虑到了一种情况:就是第一次提交有分数,而第二次提交未通过编译,按第一种写法的话,这道题将被判为-2分;但按第二种写法,仍然是第一次提交的分数。

代码如下

#include<iostream>
#include<algorithm>
#include<vector>
#include<cmath>
using namespace std;
struct person{
	int id,total,rank,acCode;
	vector<int>score;
	bool isShown;
};
int cmp(person a,person b){
	if(a.total != b.total) return a.total > b.total;
	else if(a.acCode != b.acCode) return a.acCode > b.acCode;
	return a.id < b.id;
}
int main()
{
	int n,k,m;
	scanf("%d %d %d", &n, &k, &m);
	vector<person> v(n+1);
	for(int i = 1; i <= n; i++)
		v[i].score.resize(k+1, -1);
	vector<int> full(k+1);
	for(int i = 1; i <= k; i++){
		scanf("%d", &full[i]);
	} 
	int id,pid,mark;
	for(int i = 0; i < m; i++){
		scanf("%d %d %d", &id, &pid, &mark);
		v[id].id = id;
		if(mark != -1){
			v[id].isShown = true;
			v[id].score[pid] = max(mark, v[id].score[pid]); 
		}else if(v[id].score[pid] == -1){
			v[id].score[pid] = -2;
		}
	}
	for(int i = 1; i <= n; i++){
		for(int j = 1; j <= k; j++){
			if(v[i].score[j] != -1&&v[i].score[j] != -2)v[i].total += v[i].score[j];
			if(v[i].score[j] == full[j]) v[i].acCode++;
		}
	}
	sort(v.begin()+1, v.end(), cmp);
	v[1].rank = 1;
	for(int i = 2; i <= n; i++){
		v[i].rank = i;
		if(v[i].total == v[i-1].total) v[i].rank=v[i-1].rank;
	}
	for(int i = 1; i <= n; i++){
		if(v[i].isShown==true){
			printf("%d %05d %d", v[i].rank,v[i].id,v[i].total);
			for(int j = 1; j <= k; j++){
				if(v[i].score[j] != -1&&v[i].score[j] != -2){
					printf(" %d", v[i].score[j]);
				}else if(v[i].score[j] == -1){
					printf(" -");
				}else{
					printf(" 0");
				}
			}
			printf("\n");
		}
	}
	return 0;
}
发布了110 篇原创文章 · 获赞 746 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/qq_42437577/article/details/104136616