1075 PAT Judge (25分)
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 (≤10
5
), 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.排序方法:
总成绩由大到小排序;
若总成绩相同,按满分题目数量从多到少排序;
若满分数量也相同,按学号从小到大排序;
根据上述要求构造结构函数;
总分sum,题目分数problem,学号id,满分题目数passnum,判断是否有提交过编译通过的题目flag;(题目要求道题都没有提交或者提交但没有一道题通过编译的同学不输出。)
struct User{
int Sum=0;
int Problem[6];
int Id;
int Passnum=0;
int flag=0;
}users[MAXN];
比较函数:
总分不同则分高在前;总分相同通过题数不通则通过多的在前;通过也相同则学号少的在前;
bool compare (User a,User b)
{
if(a.Sum!=b.Sum) return a.Sum>b.Sum;
else
{
if(a.Passnum!=b.Passnum) return a.Passnum>b.Passnum;
else return a.Id<b.Id;
}
}
2.输入函数
按要求输入。
注意点:因为会有重复提交,所以等全部输入完了才能计算总分;
若提交分数大于原本分数且与满分相同,则满分题数+1;
若提交分数不为-1,则标记该user不用跳过;
int N,K,M;
int p[6];
void input()
{
cin>>N>>K>>M; //输入人数,题目数,总提交数
for(int i=1;i<=K;i++)
cin>>p[i]; //每一题的总分
for(int i=1;i<=N;i++)
fill(users[i].Problem,users[i].Problem+6,-2);
int a,b;
int grade;
for(int i=0;i<M;i++)
{
cin>>a>>b>>grade;
users[a].Id=a;
if(grade!=-1) users[a].flag=1;
if(grade>users[a].Problem[b])
{
users[a].Problem[b]=grade;
if(users[a].Problem[b]==p[b])
++users[a].Passnum;
}
}
//输入完毕;计算sum
for(int i=1;i<=N;i++)
{
for(int j=1;j<=K;j++)
if(users[i].Problem[j]>0) users[i].Sum+=users[i].Problem[j];
}
}
完整代码
思路简单,注意细节;
#include<iostream>
#include<algorithm>
using namespace std;
#define MAXN 10010
struct User{
int Sum=0;
int Problem[6];
int Id;
int Passnum=0;
int flag=0;
}users[MAXN];
int N,K,M;
int p[6];
void input()
{
cin>>N>>K>>M; //输入人数,题目数,总提交数
for(int i=1;i<=K;i++)
cin>>p[i]; //每一题的总分
for(int i=1;i<=N;i++)
fill(users[i].Problem,users[i].Problem+6,-2);
int a,b;
int grade;
for(int i=0;i<M;i++)
{
cin>>a>>b>>grade;
users[a].Id=a;
if(grade!=-1) users[a].flag=1;
if(users[a].Problem[b]==0)
{
users[a].Problem[b]=grade;
if(users[a].Problem[b]==p[b])
++users[a].Passnum;
}
else if(grade>users[a].Problem[b])
{
users[a].Problem[b]=grade;
if(users[a].Problem[b]==p[b])
++users[a].Passnum;
}
}
//输入完毕;计算sum
for(int i=1;i<=N;i++)
{
for(int j=1;j<=K;j++)
if(users[i].Problem[j]>0) users[i].Sum+=users[i].Problem[j];
}
}
//存放完毕
//p里面时题目总分;
//user里面是人id,题目id,题目分数
bool compare (User a,User b)
{
if(a.Sum!=b.Sum) return a.Sum>b.Sum;
else
{
if(a.Passnum!=b.Passnum) return a.Passnum>b.Passnum;
else return a.Id<b.Id;
}
}
void ASort()
{
sort(users+1,users+N+1,compare);
}
void output()
{
int temp=0;
int index=0;
int tempindex=0;
/*5、最后一个输出,一道题都没有提交或者提交但没有一道题通过编译的同学不输出。
(一定要注意,提交没有通过编译和提交得零分完全是两个概念,
所以在这里输出的时候一定要注意,后者是需要输出的)*/
for(int i=1;i<=N;i++)
{
if(users[i].flag==0) continue;
++tempindex;
if(users[i].Sum!=temp)
{
index=tempindex;
temp=users[i].Sum;
}
printf("%d %05d %d",index,users[i].Id,users[i].Sum);
for(int j=1;j<=K;j++)
if (users[i].Problem[j]>=0) printf(" %d",users[i].Problem[j]);
else if(users[i].Problem[j]==-1) printf(" 0");
else if(users[i].Problem[j]==-2) printf(" -");
cout<<endl;
}
}
int main()
{
input();
ASort();
output();
}