题目描述
2012伦敦奥运会即将到来,大家都非常关注奖牌榜的情况,现在我们假设奖牌榜的排名规则如下:
1,首先,gold medal 数量多的排在前面;
2,其次,sliver medal 数量多的排在前面;
3,然后,bronze medal 数量多的排在前面;
4,若以上三个条件 仍无法区分名次,则以国家名称的字典序排定。
我们假设国家名称不超过20个字符,各种奖牌不超过100,切大于等于0。
输入描述:
第一行输入一个整数N(0<N<21),代表国家数量;
然后接下来的N行,每行包含一个字符串Namei表示每个国家的名称,和三个整数Gi、Si、Bi表示每个获得的gold medal、silver medal、bronze medal的数量,以空格隔开,如(China 51 20 21),具体见样例输入。
输出描述:
输出奖牌榜的依次顺序,只输出国家名称,各占一行,具体见样例输出。
测试用例
示例1:
输入
3
China 51 20 21
American 50 1 1
Japan 0 0 0
输出
China
American
Japan
示例2:
输入
4
China 51 20 21
American 52 1 1
Japan 51 22 20
Austrila 51 20 21
输出
American
Japan
Austrila
China
解题思路
本题属于典型的自定义排序类的问题。
本题在解题思路上与【Easy】找最小数-100如出一辙,唯一的区别在于本题要求输出结果为所有排序对象中指定字段的值:输出奖牌榜的依次顺序,只输出国家名称,各占一行,格式要符合题目的输出要求即可。
我们以这组测试用例为例,分析下多轮排序比较的过程:
4
China 51 20 21
American 52 1 1
Japan 51 22 20
Austrila 51 20 21
这里需要特别说明的是:
- 要点1:金牌,银牌,铜牌数都是按照数值类型从大到小进行排序;
- 要点2:当金牌,银牌,铜牌都相同时,则需要按照国家名称字符串类型按照从小到大的字典序进行排序。
这里比较容易忽视的是要点2,有的同学可能依然按照字符串的从大到小的顺序进行排序,有可能会无法通过全部的测试用例哦。
示例代码
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
using namespace std;
class Record {
public:
/**
* 国家名称
*/
string m_Country;
/**
* 金牌
*/
int m_Gi;
/**
* 银牌
*/
int m_Si;
/**
* 铜牌
*/
int m_Bi;
Record(const string &mCountry, int mGi, int mSi, int mBi) : m_Country(mCountry), m_Gi(mGi), m_Si(mSi), m_Bi(mBi) {}
};
bool myCompare(Record &record1, Record &record2) {
if (record1.m_Gi != record2.m_Gi) {
// 优先按照金牌数由大到小进行排序
return record1.m_Gi > record2.m_Gi;
} else {
// 当金牌数相同时,接着按照银牌数由大到小排序
if (record1.m_Si != record2.m_Si) {
return record1.m_Si > record2.m_Si;
} else if (record1.m_Bi != record2.m_Bi) {
return record1.m_Bi > record2.m_Bi;
} else {
string country1 = record1.m_Country;
transform(country1.begin(), country1.end(), country1.end(), ::tolower);
string country2 = record2.m_Country;
transform(country2.begin(), country2.end(), country2.end(), ::tolower);
return country1.compare(country2);
}
}
}
void myPrint(const Record &record) {
cout << record.m_Country << endl;
}
int main() {
int n;
cin >> n;
vector<Record> v;
v.reserve(n);
for (int i = 0; i < n; ++i) {
string country;
int gold, silver, copper;
cin >> country >> gold >> silver >> copper;
Record record(country, gold, silver, copper);
v.push_back(record);
}
// 自定义排序
sort(v.begin(), v.end(), myCompare);
// 输出
for_each(v.begin(), v.end(), myPrint);
return 0;
}
总结
- 分值:100分
- 难度:Easy
- 考点:多关键字排序(自定义排序)
这一类自定义排序题目的一般解题思路为:
- 输入数据获取,构造自定义排序对象。
- 根据题目中要求的字段比较逻辑,覆写比较方法compareTo().
- 执行自定义对象的排序操作。
- 按照要求将排序后的结果中制定字段进行输出。