題目:click me~
題意:PAT考試有N個考生,K道題,給出M條提交記錄。交題的分值要麼是-1(沒有通過編譯),要麼是【0,滿分】區間內的數。
要求對考生按下面規則排序:
1.總分由高到低;
2.若總分相同,則按完美解題數由高到低;
3.總分+完美解題數都相同,按准考證號由小到大排序。
輸出規則注意點:
1.總分相同,則排名相同,但每個人都佔一個排位。
2.若某考生整場考試都沒提交,或者沒有通過編譯的提交,那麼不輸出該考生信息。
3.對需要輸出的考生,考生某道題沒有提交過,那麼輸出“-”,若提交了但沒通過編譯,輸出0分。
注意一個極爲重要的邊界條件:某考生所有通過編譯的題得到的總分爲0,該考生仍然需要被輸出。
解題思路:
步驟一:要區分三種考生“全場都沒提交”、“沒有能過編譯的提交”、“有能過編譯的提交”。所以對每條提交記錄需要:
1.能過編譯,考生的flag標爲true;
2.第一次編譯沒通過,得分從-1修改爲0,便於輸出;(考生可能通過其他的題,需要被輸出)
3.當前提交是考生第一次提交得滿分,完美解題數加1;
4.當前提交考生得到更高分,則更新得分。
步驟二:提交數據處理完成後,計算每位考生總得分。
步驟三:輸出flag爲true的考生。
code:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
using namespace std;
struct node {
int no;
int sc;
bool flag;//有無通過的提交
int psc[6], solve;
}stu[10005];
int n, k, m, full[6];
void init() {
for (int i = 1;i <= n;i++) {
stu[i].no = i;
stu[i].sc = 0;
stu[i].solve = 0;
stu[i].flag = false;
memset(stu[i].psc, -1, sizeof(stu[i].psc));
}
}
bool cmp(node a, node b) {
if (a.sc != b.sc)return a.sc > b.sc;
else if (a.solve != b.solve)return a.solve > b.solve;
else return a.no < b.no;
}
int main() {
int id,pro,ps;
cin >> n >>k >> m;
init();
for (int i = 1;i <= k;i++)
cin >> full[i];
for (int i = 0;i < m;i++) {
cin >> id >> pro >> ps;
if (ps != -1)stu[id].flag = true;//若不是編譯錯誤,則有能通過編譯的提交
if (ps == -1 && stu[id].psc[pro] == -1)stu[id].psc[pro] = 0;//某題第一次編譯錯誤,分數記爲0,便於輸出;
if (ps == full[pro] && stu[id].psc[pro] < full[pro])stu[id].solve++;//某題第一次得滿分,完美解題數+1;
if (ps > stu[id].psc[pro])stu[id].psc[pro] = ps;//某題獲得更高分,則覆蓋
}
for (int i = 1;i <= n;i++) {
for (int j = 1;j <= k;j++) {
if (stu[i].psc[j] != -1)//計算總分
stu[i].sc += stu[i].psc[j];
}
}
sort(stu + 1, stu + n + 1, cmp);
int r=1;
for (int i = 1;i <=n&&stu[i].flag==true;i++) {
if (i > 0 && stu[i].sc != stu[i - 1].sc) {
r = i ;//當前考生與上一個分數不同時,r更新爲i
}
printf("%d %05d %d",r,stu[i].no,stu[i].sc);
for (int j = 1;j <= k;j++) {
if (stu[i].psc[j] == -1)
cout << " -";
else
cout << " " << stu[i].psc[j];
}
cout << endl;
}
return 0;
}