各位好遭铺,我是董佳凝/手動(dòng)狗頭.我?guī)е鴾喩淼母斡只貋?lái)了卿叽。
今天是排序的第二個(gè)范例彤断。
BACKGROUND
To evaluate the performance of our first year CS majored students, we consider their grades of three courses only: C - C Programming Language, M - Mathematics (Calculus or Linear Algrbra), and E - English. At the mean time, we encourage students by emphasizing on their best ranks -- that is, among the four ranks with respect to the three courses and the average grade, we print the best rank for each student.
For example, The grades of C, M, E and A - Average of 4 students are given as the following:
StudentID C M E A
310101 98 85 88 90
310102 70 95 88 84
310103 82 87 94 88
310104 91 91 91 91
Then the best ranks for all the students are No.1 since the 1st one has done the best in C Programming Language, while the 2nd one in Mathematics, the 3rd one in English, and the last one in average.
Input Specification:
Each input file contains one test case. Each case starts with a line containing 2 numbers N and M (≤2000), which are the total number of students, and the number of students who would check their ranks, respectively. Then N lines follow, each contains a student ID which is a string of 6 digits, followed by the three integer grades (in the range of [0, 100]) of that student in the order of C, M and E. Then there are M lines, each containing a student ID.
Output Specification:
For each of the M students, print in one line the best rank for him/her, and the symbol of the corresponding rank, separated by a space.
The priorities of the ranking methods are ordered as A > C > M > E. Hence if there are two or more ways for a student to obtain the same best rank, output the one with the highest priority.If a student is not on the grading list, simply output N/A.
為了嚴(yán)謹(jǐn)漱贱,我把題目粘過(guò)來(lái)了峡钓,但是沒(méi)想到這題目字?jǐn)?shù)直接占我整篇文章的半壁江山/逃
但我又知道你是肯定不去讀或者早就在別處讀過(guò)這段題意的 /手動(dòng)摳鼻
老規(guī)矩妓笙,精簡(jiǎn)題目的廢話,我來(lái)解釋一哈
就是有一堆童鞋能岩,每人有四個(gè)分?jǐn)?shù)寞宫,C程序分兒,數(shù)學(xué)分兒拉鹃,英語(yǔ)分兒還有平均分兒氣質(zhì)兒化音
讓我們針對(duì)每一種科目辈赋,對(duì)童鞋們排名鲫忍。(也就是有四個(gè)排名。嗯哪钥屈,平均分也要個(gè)排名不行拔蛎瘛?/戰(zhàn)術(shù)后仰)
然后題目系統(tǒng)會(huì)給出一些詢問(wèn)焕蹄,問(wèn)某個(gè)某個(gè)ID的童鞋逾雄,他哪個(gè)科目最偏科擅長(zhǎng)啊腻脏? 請(qǐng)你給出這個(gè)童鞋擅長(zhǎng)的科目還有他在該科目下排第幾鸦泳。
木了~
既然也是排序,我們不妨把這個(gè)題目和德才論的做一下小小的對(duì)比永品,看看差別在哪做鹰,有助于我們的進(jìn)步。
你會(huì)發(fā)現(xiàn)鼎姐,德才論的特點(diǎn)是針對(duì)學(xué)生的綜合表現(xiàn)钾麸,定類別做排名,炕桨,不給你體現(xiàn)自己特長(zhǎng)的機(jī)會(huì)(尤其是德才論里面被視為小人的饭尝,IQ越高越被貶斥)因此,在處理這個(gè)問(wèn)題的時(shí)候献宫,我們把注意力放在如何編寫compare函數(shù)就可以了钥平。
本題略微有點(diǎn)區(qū)別,在于姊途,涉瘾。但是我們不需要去寫四個(gè)for循環(huán),相反的捷兰,我們可以從答案里面學(xué)到一個(gè)技巧立叛,一個(gè)for就可以拿到四個(gè)排名。因此贡茅,這道題目我們最大的收獲當(dāng)屬秘蛇,如何一次弄得多個(gè)排名。
在落實(shí)到代碼之前顶考,我給出注意事項(xiàng):
1.如果題目問(wèn)到了一個(gè)ID不存在的鬼彤叉,你就用N/A抨擊它。
2.如果被問(wèn)到的童鞋有幾個(gè)科目排名相同村怪,需要按照 平均 > C語(yǔ)言 > 數(shù) > 英 順序給出最秀的排名秽浇。
下面是代碼
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
struct Student //每個(gè)同學(xué)存儲(chǔ)id ,以及四個(gè)數(shù)字
{
int id;
int grade[4];
} stu[2010];
char course[4] =
{
'A',
'C',
'M',
'E',
}; //這是為了最后給出“最優(yōu)秀科目”用的char數(shù)組甚负,順序正是科目的優(yōu)先級(jí)
int Rank[1000000][4] = {0};
/*
這里rank設(shè)置了1000000柬焕,不是意味著有這么多人都等著排序审残,而是為了讓這么大的數(shù)字完全涵蓋住咱們的id
是的,id通過(guò)int存儲(chǔ)斑举,讓訪問(wèn)更方便
tip:id能int存起來(lái)的搅轿,就別用char*[]去存
*/
int now; //這個(gè)now就是我們獲取多個(gè)排名的 “鑰匙”
bool cmp(Student a, Student b) //這個(gè)compare很精簡(jiǎn)。畢竟一種排名就看一個(gè)指標(biāo)富玷,跟 德才論 明顯區(qū)別開(kāi)來(lái)
{
return a.grade[now] > b.grade[now];
}
int main()
{
int n, m;
scanf("%d %d", &n, &m);//存進(jìn)n個(gè)人璧坟,以及m個(gè)詢問(wèn)
for (int i = 0; i < n; i++)
{
//放分?jǐn)?shù)
scanf("%d%d%d%d", &stu[i].id, &stu[i].grade[1], &stu[i].grade[2], &stu[i].grade[3]);
//算均分,最后這個(gè)0.5加不加無(wú)所謂赎懦,都能pass
stu[i].grade[0] = round((stu[i].grade[1] + stu[i].grade[2] + stu[i].grade[3]) / 3.0) + 0.5;
}
for (now = 0; now < 4; now++)
{
sort(stu, stu + n, cmp);//吶喊一聲雀鹃,sort牛X
Rank[stu[0].id][now] = 1;//定下來(lái)第一,以后的依次排下去
for (int i = 1; i < n; i++)
{
if (stu[i].grade[now] == stu[i - 1].grade[now])//要是分?jǐn)?shù)雷同了
{
Rank[stu[i].id][now] = Rank[stu[i - 1].id][now];//排名就一樣
}
else
{
Rank[stu[i].id][now] = i + 1;//跟前面的不一樣励两,就乖乖往后排黎茎,
/*
注意這里是 i + 1 ,不是 Rank[stu[i - 1].id][now] +1 ,
我想大家都看過(guò)成績(jī)單当悔,最狗的時(shí)候兩人并列第一傅瞻,本應(yīng)分?jǐn)?shù)排名第二的也只能乖乖第三了
明白吧?
*/
}
}
}
int query;
for (int i = 0; i < m; i++)
{
scanf("%d", &query);
if (Rank[query][0] == 0)
/*
沒(méi)有同學(xué)的排名可以是0盲憎,因此這個(gè)人一定是鬼
Rank[query][這里寫 1或者2或者3] == 0 都可以通過(guò)
*/
{
printf("N/A\n");//懟它
}
else
{
int k = 0;
for (int j = 0; j < 4; j++)
{
if (Rank[query][j] < Rank[query][k])
{
k = j;//找到人家排名數(shù)字最小的(也就是排名靠前的)
}
}
printf("%d %c\n", Rank[query][k], course[k]);
}
}
return 0;
}
以上我給出了詳細(xì)的解釋嗅骄,希望有所幫助。
來(lái)饼疙,把課代表押上來(lái)5Ф痢!
今天我們主要get到了一個(gè)技巧宏多。也就是如何一次撈到多個(gè)循環(huán)的結(jié)果。
亮點(diǎn)
準(zhǔn)備工作:
int now;
bool cmp(Student a, Student b)
{
return a.grade[now] > b.grade[now];
}
應(yīng)用:
for (now = 0; now < 4; now++)
{
sort(stu, stu + n, cmp);
/*下面是設(shè)定排名的代碼澡罚,不是這里討論的重點(diǎn)*/
}
一下子清晰明了了伸但,對(duì)嗎?
隨著now的自增留搔,stu就會(huì)根據(jù)要求更胖,進(jìn)行排序。
只需要把精力放在如何在當(dāng)前的順序下隔显,給定同學(xué)們的排名就可以了却妨。
開(kāi)始吟唱~
這里是我的算法筆記,有復(fù)制粘貼就能跑括眠,提交就是滿分的代碼彪标。也是記錄成長(zhǎng)點(diǎn)點(diǎn)滴滴的平臺(tái)。
如果我想起來(lái)什么可以補(bǔ)充的掷豺,會(huì)再來(lái)更改的捞烟。
今天到這了薄声,886~