1095 解碼PAT准考證——C++實現
阿新 • • 發佈:2018-12-11
題目
1095 解碼PAT准考證 (25 分)
PAT 准考證號由 4 部分組成:
- 第 1 位是級別,即
T
代表頂級;A
代表甲級;B
代表乙級;- 第 2~4 位是考場編號,範圍從 101 到 999;
- 第 5~10 位是考試日期,格式為年、月、日順次各佔 2 位;
- 最後 11~13 位是考生編號,範圍從 000 到 999。
現給定一系列考生的准考證號和他們的成績,請你按照要求輸出各種統計資訊。
輸入格式:
輸入首先在一行中給出兩個正整數 N(≤104)和 M(≤100),分別為考生人數和統計要求的個數。
接下來 N 行,每行給出一個考生的准考證號和其分數(在區間 [0,100] 內的整數),其間以空格分隔。
考生資訊之後,再給出 M 行,每行給出一個統計要求,格式為:
型別 指令
,其中
型別
為 1 表示要求按分數非升序輸出某個指定級別的考生的成績,對應的指令
則給出代表指定級別的字母;型別
為 2 表示要求將某指定考場的考生人數和總分統計輸出,對應的指令
則給出指定考場的編號;型別
為 3 表示要求將某指定日期的考生人數分考場統計輸出,對應的指令
則給出指定日期,格式與准考證上日期相同。輸出格式:
對每項統計要求,首先在一行中輸出
Case #: 要求
,其中#
是該項要求的編號,從 1 開始;要求
即複製輸入給出的要求。隨後輸出相應的統計結果:
型別
為 1 的指令,輸出格式與輸入的考生資訊格式相同,即准考證號 成績
。對於分數並列的考生,按其准考證號的字典序遞增輸出(題目保證無重複准考證號);型別
為 2 的指令,按人數 總分
的格式輸出;型別
為 3 的指令,輸出按人數非遞增順序,格式為考場編號 總人數
。若人數並列則按考場編號遞增順序輸出。如果查詢結果為空,則輸出
NA
。輸入樣例:
8 4 B123180908127 99 B102180908003 86 A112180318002 98 T107150310127 62 A107180908108 100 T123180908010 78 B112160918035 88 A107180908021 98 1 A 2 107 3 180908 2 999
輸出樣例:
Case 1: 1 A A107180908108 100 A107180908021 98 A112180318002 98 Case 2: 2 107 3 260 Case 3: 3 180908 107 2 123 2 102 1 Case 4: 2 999 NA
演算法
因為型別1,3兩個輸出的排序規則類似,構建一個結構體陣列分別來儲存學生和考場的情況。其中學生儲存的是准考證號和成績,考場儲存的是考場編號和人數。建立兩個結構體陣列stu和dat。stu按考生等級將考生分為3類分別儲存。dat按日期將考場分別儲存。再建立三個map:Nm,Sm,Dm。Nm記錄每個考場出現的次數,Sm記錄每個考場的總分。Dm記錄每個日期,每增加一個日期對應的Key值為上一個日期對應的key值加1,每個日期的key值就可以作為dat陣列的下標。最後對應3種類型分別排序輸出。
注意:
1.使用scanf,printf輸入輸出。
2.型別2輸出中考場的人數為該考場出現的總次數,而型別3輸出中考場的人數為對應日期的考場出現的次數。
3.dat陣列應定義為動態陣列,否則容易產生段錯誤。
程式碼
#include<iostream>
#include<algorithm>
#include<string>
#include<vector>
#include<map>
using namespace std;
struct StudentOrHall
{
string id; //stu陣列中為準考證號,dat陣列中為考場編號
int number; //stu陣列中為考生成績,dat陣列中為考場人數
};
bool cmp(struct StudentOrHall s1, struct StudentOrHall s2)
{
if (s1.number != s2.number) return s1.number > s2.number;
return s1.id < s2.id;
}
int main()
{
int n, m, i, j, k = 1, score, date, command;
vector<struct StudentOrHall> stu[3];
vector<vector<struct StudentOrHall>> dat;
string Hid, level = "TAB";
char Sid[13], s[6];
scanf("%d %d", &n, &m);
map<string, int> Nm, Sm;
map<int, int> Dm;
for (i = 0; i < n; i++)
{
scanf("%s %d", &Sid, &score);
stu[level.find(Sid[0])].push_back({ Sid,score });
Hid = string(Sid).substr(1, 3);
date = stoi(string(Sid).substr(4, 6));
if (!Dm[date]) Dm[date] = k++; //設定每個日期在dat陣列中對應的下標
dat.resize(k); //動態調整dat陣列大小
for (j = 0; j < dat[Dm[date] - 1].size() && dat[Dm[date] - 1][j].id != Hid; j++); //判斷該日期相應考場編號是否出現過
if (j == dat[Dm[date] - 1].size()) dat[Dm[date] - 1].push_back({ Hid,0 });
dat[Dm[date] - 1][j].number++; //該日期相應考場的人數+1
Nm[Hid]++; //考場的總人數
Sm[Hid] += score; //考場的總成績
}
for (i = 0; i < m; i++)
{
scanf("%d %s", &command, &s);
printf("Case %d: %d %s\n", i + 1, command, s);
if (command == 1)
{
command = level.find(s[0]);
sort(stu[command].begin(), stu[command].end(), cmp);
for (j = 0; j < stu[command].size(); j++)
printf("%s %d\n", stu[command][j].id.c_str(), stu[command][j].number);
if (!j) printf("NA\n");
}
else if (command == 2)
{
if (Nm[s]) printf("%d %d\n", Nm[s], Sm[s]);
else printf("NA\n");
}
else
{
command = stoi(s);
if (!Dm[command]) printf("NA\n");
else
{
sort(dat[Dm[command] - 1].begin(), dat[Dm[command] - 1].end(), cmp);
for (j = 0; j < dat[Dm[command] - 1].size(); j++)
printf("%s %d\n", dat[Dm[command] - 1][j].id.c_str(), dat[Dm[command] - 1][j].number);
}
}
}
return 0;
}