题意
输入k个程序的每个程序的满分分数,再输入m条用户提交的记录。按要求进行分数的排序最后输出。是一道结构体的复杂排序
思路分析
首先明确本题的输出要求:
- 编译失败的提交分数为-1。
- 只有至少成功提交过一次程序(没有编译失败),的用户才会被排序。可以通过在结构体中设置一个
bool isshown
标志实现,当输入的grade != -1时,则isshown
设置为true。 - 要求输出得失每条程序的最高的提交分数,可以边输入边更新该程序的最高分
- 对于排序中的用户,如果编译失败,则该提交对应的程序分数为
0
,而没有提交的程序,即输出-
。 - cmp按照总分从高到低排序,总分相等时按照完整解决程序个数排序,解决个数相等时,按照id从小到大。
结构体的写法:按照所需输出的要求,结构体应写成如下形式
struct record{
int user,id,ranked,num,total;
//user代表用户名,id代表题号,ranked排名,num代表得到满分的次数,tota总分
int grade[6]; //各个程序的得分
bool isshown = false; //默认为false表示没有成功的提交
}rec[maxn];
细节性太多,直接看代码吧。
参考代码:
#include
using namespace std;
const int maxn = 1e4+10;
int a[6];
struct record{
int user,id,ranked,num,total;
int grade[6]; //各科分数
bool isshown = false; //默认为false表示没有成功的提交
}rec[maxn];
int n,k,m;
bool cmp(const record &a,const record &b) {
if(a.total != b.total) return a.total > b.total;
else if(a.num != b.num) return a.num > b.num;
else return a.user < b.user;
}
int main(void) {
int user,id,grade;
cin>>n>>k>>m;
for(int i = 1;i <= k;i++) scanf("%d",&a[i]);
for(int i = 1;i <= n;i++) fill(rec[i].grade,rec[i].grade+6,-2); //-2代表所有程序未提交
for(int i = 0;i < m;i++) {
scanf("%05d %d %d",&user,&id,&grade);
rec[user].user = user; //注意此处的写法是rec[user]而不是rec[i]。
rec[user].grade[id] = max(rec[user].grade[id],grade); //更新对应程序的最高分
if(grade != -1) rec[user].isshown = true; //出现了分数不为-1,则设置标记
}
//遍历所有的用户,获得总分数以及完整通过程序的个数num
for(int i = 1;i <= n;i++) {
for(int j = 1;j <= k;j++) {
if(rec[i].grade[j] != -1 && rec[i].grade[j] != -2) //提交了并且编译通过则加到总分中
rec[i].total += rec[i].grade[j];
if(rec[i].grade[j] == a[j]) rec[i].num++; //如果是满分,则完整通过个数+1
}
}
//获得排名
sort(rec+1,rec+1+n,cmp);
rec[1].ranked = 1;
for(int i = 2;i <= n;i++) {
if(rec[i].total == rec[i-1].total) rec[i].ranked = rec[i-1].ranked;
else rec[i].ranked = i;
}
for(int i = 1;i <= n;i++) {
if(rec[i].isshown == true) {
printf("%d %05d %d ",rec[i].ranked,rec[i].user,rec[i].total);
for(int j = 1;j <= k;j++) {
if(j > 1) cout<<" ";
if(rec[i].grade[j] == -1) cout<<"0";
else if(rec[i].grade[j] == -2) cout<<"-";
else cout<