题意:给三个分数CME,加上算出来的平均分(要四舍五入,测试了才发现的),4个分数对应有4个排名,给出他们的最好排名(聊以自慰嘛→_→),最后根据给出的查询编号,查询出他们的最好排名和对应学科,或者查无此人。
AC代码:
//1012 The Best Rank (25分) https://pintia.cn/problem-sets/994805342720868352/problems/994805502658068480
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
struct student {
char id[7];
int score[4];
int rank[4];
int best;//最好排名
int best_id;//最好排名对应科目ACME
}s[2020];
char id[2020][7] = { 0 };
char sub[5] = "ACME";
bool cmp_c(student s1, student s2)
{
if (s1.score[1] != s2.score[1]) return s1.score[1] > s2.score[1];
else return strcmp(s1.id, s2.id) < 0;
}
bool cmp_m(student s1, student s2)
{
if (s1.score[2] != s2.score[2]) return s1.score[2] > s2.score[2];
else return strcmp(s1.id, s2.id) < 0;
}
bool cmp_e(student s1, student s2)
{
if (s1.score[3] != s2.score[3]) return s1.score[3] > s2.score[3];
else return strcmp(s1.id, s2.id) < 0;
}
bool cmp_avg(student s1, student s2)
{
if (s1.score[0] != s2.score[0]) return s1.score[0] > s2.score[0];
else return strcmp(s1.id, s2.id) < 0;
}
void v_sort(student* s, bool (*cmp)(student, student), int n)
{
sort(s, s + n, cmp);
}
void find_best(student* s) {//重点函数
int min = 2020;
for (int i = 0; i < 4; i++) {
if (s->rank[i] < min) {
min = s->rank[i];
s->best_id = i;
}
}
s->best = min;
}
int main()
{
int N, M;
scanf("%d%d", &N, &M);
for (int i = 0; i < N; i++) {
scanf("%s %d %d %d", s[i].id, &s[i].score[1], &s[i].score[2], &s[i].score[3]);
s[i].score[0] = (int)((float)(s[i].score[1] + s[i].score[2] + s[i].score[3]) / 3 + 0.5);//四舍五入
}
v_sort(s, cmp_c, N);//对各学科排序,并得出各学科的排名
s[0].rank[1] = 1;
for (int i = 1; i < N; i++) {
if (s[i].score[1] == s[i - 1].score[1])
s[i].rank[1] = s[i - 1].rank[1];
else s[i].rank[1] = i + 1;
}
v_sort(s, cmp_m, N);
s[0].rank[2] = 1;
for (int i = 1; i < N; i++) {
if (s[i].score[2] == s[i - 1].score[2])
s[i].rank[2] = s[i - 1].rank[2];
else s[i].rank[2] = i + 1;
}
v_sort(s, cmp_e, N);
s[0].rank[3] = 1;
for (int i = 1; i < N; i++) {
if (s[i].score[3] == s[i - 1].score[3])
s[i].rank[3] = s[i - 1].rank[3];
else s[i].rank[3] = i + 1;
}
v_sort(s, cmp_avg, N);
s[0].rank[0] = 1;
for (int i = 1; i < N; i++) {
if (s[i].score[0] == s[i - 1].score[0])
s[i].rank[0] = s[i - 1].rank[0];
else s[i].rank[0] = i + 1;
}
//对于每个人,求得其最好排名和对应的科目ACME
for (int i = 0; i < N; i++) {
find_best(s + i);
}
for (int i = 0; i < M; i++) {//读入m个待查id
scanf("%s", id[i]);
}
for (int i = 0; i < M; i++) {
bool flag = false;
for (int j = 0; j < N; j++) {
if (strcmp(id[i], s[j].id) == 0) {
flag = true;
printf("%d %c\n", s[j].best, sub[s[j].best_id]);
}
}
if (!flag) printf("N/A\n");
}
return 0;
}
标准答案:
//1012 The Best Rank (25分) https://pintia.cn/problem-sets/994805342720868352/problems/994805502658068480
#include <cstdio>
#include <algorithm>
int now;//全局变量,0-3对应四门课,可以省去4个不同的cmp函数
using namespace std;
struct student {
int id;
int score[4];
}s[2020];
int Rank[1000000][4] = { 0 };//rank[id][0]-[3]为4门课ACME对应的排名//C++有一个rank,为了不重名改为大写
char sub[5] = "ACME";
bool cmp(student s1, student s2)
{
if (s1.score[now] != s2.score[now]) return s1.score[now] > s2.score[now];
else
return s1.id < s2.id;
}
int main()
{
int N, M;
scanf("%d%d", &N, &M);
for (int i = 0; i < N; i++) {
scanf("%d %d %d %d", &s[i].id, &s[i].score[1], &s[i].score[2], &s[i].score[3]);
s[i].score[0] = (int)((float)(s[i].score[1]+ s[i].score[2]+ s[i].score[3]) / 3+0.5);//四舍五入
}
for (now = 0; now < 4; now++) {
sort(s, s + N, cmp);
Rank[s[0].id][now] = 1;
for (int i = 1; i < N; i++) {
if (s[i].score[now]==s[i-1].score[now]) {
Rank[s[i].id][now] = Rank[s[i - 1].id][now];
}
else
{
Rank[s[i].id][now] = i + 1;
}
}
}
int query;
while (M--)
{
scanf("%d", &query);
int k = 0;
if (Rank[query][0] == 0) printf("N/A\n");
else
{
for (int i = 0; i < 4; i++) {
if (Rank[query][i] < Rank[query][k])
k = i;
}
printf("%d %c\n", Rank[query][k], sub[k]);
}
}
return 0;
}
总结一下标准答案的可取之处:
1.id使用int而不是string
我看到题目a string of 6 digits想也没想就直接用字符数组存了。id设为int,配合上Rank数组(rank和c++本身的什么东西重名了)典型的用空间换时间,我需要遍历查找是否有这样的字符串,而数组可以随机访问,O1的复杂度,确实给力。
2.全局变量now
这个可真是厉害了,对比就可以发现,这个全局变量一下子就省去了四个不同的cmp函数和四次寻找排名,代码冗余度一下子减少好多,这也是标准答案的代码量只有我的一半的原因。其实当时我自己写着写着都怀疑人生了,而且最一开始我还不是用数组存rank的,到了要遍历寻找最小排名的时候才改过来的。
3.rank数组
这个二维数组结合了id和4门课的排名,把搜索id和寻找id对应最好排名结合起来,而且就用1个下标,直接输出最好排名和对应课程,都不需要存下来。除了妙我还能说什么呢?