【来源】
【分析】
本题模拟的是PAT的评分和排名系统。
做这种给出的信息很大,要求很多的题目时,我采用的策略一般是渐进式编程。刚开始码代码时,不必将所有的条件都考虑在内,只关心大致的框架和逻辑。完成框架以后再逐步完善细节。因此以下的解题思路并非一开始就是这么想的,而是后验的,考虑的细节已经比较全面了。
具体解题思路如下:
首先建立起考生数据模型(struct),包含的信息有考生的id、每道题所得到的分数、得到的总分、排名、该记录是否有效、完美解决问题的数量以及提交次数。初始化时,将考生每题的得分初始化为-1,代表该考生未进行任何提交。
然后依据排名规则写出compare函数来对考生进行sort。具体规则为:首先按总分降序排名,总分一样的话按照完美解决问题的个数降序排名,个数一样的再按照id升序排名。
考虑到考生的数量在10000以内,所以开一个长度为10001的vector。对于每次提交,如果发现编译错误(partialscore为-1),此题不得分;否则记有效提交次数加1。如果此次提交的题目比上次分数高,则更新该考生的此题分数,并且如果此题分数达到满分,记完美解决的问题数加1。
经过上一轮之后,接下来我们需要把有效的记录提取出来,并且把从未进行过任何有效提交的考生排除出去,顺便计算出考生的总分。
之后开始根据刚开始写好的compare函数对考生进行排序。需注意总分相同的考生名次应该相同。
排序之后输出。对于考生没有提交过的题目(得分为-1),输出“-”即可。
【代码】
#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
struct User{
int id;
int scores[5];
int totalscore;
int rank;
bool valid;
int perfect;
int submits;
User(){
valid = false;
rank = 0;
totalscore = 0;
for (int i = 0; i < 5; ++i){
scores[i] = -1;
}
perfect = 0;
submits = 0;
}
};
bool compare(User u1, User u2){
if (u1.totalscore != u2.totalscore){
return u1.totalscore > u2.totalscore;
}
else{
if (u1.perfect != u2.perfect){
return u1.perfect > u2.perfect;
}
else{
return u1.id < u2.id;
}
}
}
int main()
{
int N, K, M;
scanf("%d%d%d", &N, &K, &M);
int *p = new int[K];
for (int i = 0; i < K; ++i){
scanf("%d", &p[i]);
}
vector<User> users(10001);
for (int i = 0; i < M; ++i){
int user_id, problem_id, partial_score;
scanf("%d%d%d", &user_id, &problem_id, &partial_score);
users[user_id].id = user_id;
users[user_id].valid = true;
if (partial_score == -1){
partial_score = 0;
}
else{
++users[user_id].submits;
}
if (partial_score > users[user_id].scores[problem_id - 1]){
users[user_id].scores[problem_id - 1] = partial_score;
if (partial_score == p[problem_id - 1]){
++users[user_id].perfect;
}
}
}
vector<User> dense;
for (int i = 0; i < 10001; ++i){
if (users[i].valid){
for (int j = 0; j < K; ++j){
if (users[i].scores[j] != -1){
users[i].totalscore += users[i].scores[j];
}
}
if (users[i].submits > 0){
dense.push_back(users[i]);
}
}
}
sort(dense.begin(), dense.end(), compare);
dense[0].rank = 1;
for (int i = 1; i < dense.size(); ++i){
dense[i].rank = i + 1;
if (dense[i].totalscore == dense[i-1].totalscore){
dense[i].rank = dense[i-1].rank;
}
}
for (int i = 0; i < dense.size(); ++i){
printf("%d %05d %d", dense[i].rank, dense[i].id, dense[i].totalscore);
for (int j = 0; j < K; ++j){
if (dense[i].scores[j] != -1){
printf(" %d", dense[i].scores[j]);
}
else{
printf(" -");
}
}
printf("\n");
}
delete[] p;
system("pause");
return 0;
}
【点评】
此题要求甚多且有陷阱,考察较高水平的抽象能力和问题解决能力。需注意区分提交答案错误与没有进行有效提交(即通过编译器的提交)是有区别的。不注意这种区别就会掉入陷阱。