#include <cfloat> #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<stdlib.h> #include<math.h> #include<algorithm> using namespace std; //p36 习题3.4 奥运排序问题 //注意:本题意图输入N个国家的信息,但要依据所给出的M个国家号对这M个国家进行4中排序方式 //定义一个国家的结构体类型 typedef struct { //注意一定要用float类型,在计算金牌/奖牌比例时如果int型则会进行整除,会忽略小数部分,排序不精确 float gold, ward, population; //金牌,奖牌,人口(百万)数目 float goldRate, wardRate; //金牌,奖牌的人口比例 int rank1, rank2, rank3, rank4; //此国家的不同排序方式(方法1,2,3,4)中的排名 int order; //国家号 } Country; //国家信息之间的赋值,将国家类型countryX的值赋给countryY void convertInfo(Country& countryX, Country& countryY) { countryY.gold = countryX.gold; countryY.ward = countryX.ward; countryY.population = countryX.population; //目前用不到(因为只对那M个要排序的国家进行计算) //countryY.goldRate = countryX.goldRate; //countryY.wardRate = countryX.wardRate; countryY.rank1 = countryX.rank1; countryY.rank2 = countryX.rank2; countryY.rank3 = countryX.rank3; countryY.rank4 = countryX.rank4; countryY.order = countryX.order; } //自定义排序规则1(比较金牌个数)(降序排列) bool compGold(Country countryX, Country countryY) { return countryX.gold > countryY.gold; } bool compWard(Country countryX, Country countryY) { return countryX.ward > countryY.ward; } bool compGoldRate(Country countryX, Country countryY) { return countryX.goldRate > countryY.goldRate; } bool compWardRate(Country countryX, Country countryY) { return countryX.wardRate > countryY.wardRate; } //根据国家号进行排序(升序),恢复原有的序列 bool compOrder(Country countryX, Country countryY) { return countryX.order < countryY.order; } int main() { int N, M; //N个国家,要排序的有M个(最后一行给出M个国家号) Country countries[100]; //存储N个国家的信息 Country sortCountries[100]; //存储M个待排序的国家信息 while (scanf("%d%d", &N, &M) != EOF) { for (int i = 0; i < N; ++i) { scanf("%d%d%d", &countries[i].gold, &countries[i].ward, &countries[i].population); //为N个国家定义其国家号(0 - N-1) countries[i].order = i; } int sortNum; //定义以下要排序的国家号(M个),并将相应的国家信息转移到待排序的国家数组中(这里用到一个复制信息的函数,减少操作) for (int i = 0; i < M; ++i) { scanf("%d", &sortNum); convertInfo(countries[sortNum], sortCountries[i]); //只对要排序的M个国家计算金牌,奖牌比例 if (sortCountries[i].population != 0) { sortCountries[i].goldRate = sortCountries[i].gold / sortCountries[i].population; sortCountries[i].wardRate = sortCountries[i].ward / sortCountries[i].population; } //隐含 sortCountries[i].population == 0 该条件 else { if (sortCountries[i].gold == 0) { sortCountries[i].goldRate = 0; } else { sortCountries[i].goldRate = FLT_MAX; } if (sortCountries[i].ward == 0) { sortCountries[i].wardRate = 0; } else { sortCountries[i].wardRate = FLT_MAX; } } } //之后的排序都是对 待排序的国家数组 sortCountries[]进行操作 // ----------------------------------------------------------- //排序方式1,根据金牌个数进行降序排序 sort(sortCountries, sortCountries + M, compGold); //定义 当前序号 记录排序方式1的各国的排名,并且存储在各个国家的rank1中,表示各国排序方式1的排名(以下同理) int curOrder = 0; for (int i = 0; i < M; ++i) { if (0 == i) { //数组中首个国家自然第一 sortCountries[i].rank1 = ++curOrder; } else if (sortCountries[i - 1].gold == sortCountries[i].gold) { //上一个国家的金牌数目和当前国家的金牌数目相等,则排名并列,但是curOrder仍然+1 sortCountries[i].rank1 = sortCountries[i - 1].rank1; ++curOrder; } else { //因为已经按照方式1排序,仅剩下一种情况(就是上一个国家金牌数 > 本次国家金牌数) sortCountries[i].rank1 = ++curOrder; } } //排序方式2,根据奖牌个数进行降序排序 sort(sortCountries, sortCountries + M, compWard); //重置curOrder curOrder = 0; for (int i = 0; i < M; ++i) { if (0 == i) { //数组中首个国家自然第一 sortCountries[i].rank2 = ++curOrder; } else if (sortCountries[i - 1].ward == sortCountries[i].ward) { //上一个国家的奖牌数目和当前国家的奖牌数目相等,则排名并列,但是curOrder仍然+1 sortCountries[i].rank2 = sortCountries[i - 1].rank2; ++curOrder; } else { //因为已经按照方式2排序,仅剩下一种情况(就是上一个国家奖牌数 > 本次国家奖牌数) sortCountries[i].rank2 = ++curOrder; } } //排序方式3,根据金牌/人口比例进行降序排序 sort(sortCountries, sortCountries + M, compGoldRate); //重置curOrder curOrder = 0; for (int i = 0; i < M; ++i) { if (0 == i) { //数组中首个国家自然第一 sortCountries[i].rank3 = ++curOrder; } else if (sortCountries[i - 1].goldRate == sortCountries[i].goldRate) { //上一个国家的金牌人口比例和当前国家的奖牌人口比例相等,则排名并列,但是curOrder仍然+1 sortCountries[i].rank3 = sortCountries[i - 1].rank3; ++curOrder; } else { //因为已经按照方式3排序,仅剩下一种情况(就是上一个国家金牌人口比例 > 本次国家金牌人口比例) sortCountries[i].rank3 = ++curOrder; } } //排序方式4,根据奖牌/人口比例进行降序排序 sort(sortCountries, sortCountries + M, compWardRate); //重置curOrder curOrder = 0; for (int i = 0; i < M; ++i) { if (0 == i) { //数组中首个国家自然第一 sortCountries[i].rank4 = ++curOrder; } else if (sortCountries[i - 1].wardRate == sortCountries[i].wardRate) { //上一个国家的奖牌人口比例和当前国家的奖牌人口比例相等,则排名并列,但是curOrder仍然+1 sortCountries[i].rank4 = sortCountries[i - 1].rank4; ++curOrder; } else { //因为已经按照方式4排序,仅剩下一种情况(就是上一个国家奖牌比例数 > 本次国家奖牌比例数) sortCountries[i].rank4 = ++curOrder; } } //处理完毕,需要排序的M个国家的各个排序方式的排名已经记录,准备输出 //根据国家号恢复原有顺序 sort(sortCountries, sortCountries + M, compOrder); //输出规则:最佳排名的排名方式 和 排名 格式为: 排名:排名方式 //如果一个国家中各个排名方式的排名有相同的,则输出排名方式最小的那种排名, //对于排名方式,金牌总数(1) < 奖牌总数(2) < 金牌人口比例(3) < 奖牌人口比例(4) for (int i = 0; i < M; ++i) { if (sortCountries[i].rank1 <= sortCountries[i].rank2 && sortCountries[i].rank1 <= sortCountries[i].rank3 && sortCountries[i].rank1 <= sortCountries[i].rank4) { //如果排名方式1的排名方式靠前或者与其他齐平则打印rank1 printf("%d:%d\n", sortCountries[i].rank1, 1); } else if (sortCountries[i].rank2 < sortCountries[i].rank1 && sortCountries[i].rank2 <= sortCountries[i].rank3 && sortCountries[i].rank2 <= sortCountries[i].rank4) { //如果排名方式2的排名方式比方式1靠前或者与其他齐平则打印rank2 printf("%d:%d\n", sortCountries[i].rank2, 2); } else if (sortCountries[i].rank3 < sortCountries[i].rank1 && sortCountries[i].rank3 < sortCountries[i].rank2 && sortCountries[i].rank3 <= sortCountries[i].rank4) { printf("%d:%d\n", sortCountries[i].rank3, 3); } else if (sortCountries[i].rank4 < sortCountries[i].rank1 && sortCountries[i].rank4 <= sortCountries[i].rank2 && sortCountries[i].rank4 < sortCountries[i].rank3) { //如果排名方式4的排名比其他的方式都要靠前而非齐平,则打印rank4 printf("%d:%d\n", sortCountries[i].rank4, 4); } } } return 0; }
通过借鉴各位大佬的经验,最终选定了使用 (4中排序规则)的解题思路
特别感谢以上大佬,避免了不少坑,在本章代码注释中尽力写的很详细
1.定义一个国家结构体,循环输入,先满足输入条件,在输入的过程中对各个国家进行初始化
2根据国家号对要排序的国家取出,放入定义的一个待排序国家数组中
3.接下来仅对待排序数组中的国家进行处理
4.定义5中排序规则,对应的排序方法1,2,3,4以及国家号(升序排序)目的在于最后恢复原来的国家顺序
5.依此对着4种排序方法,排序,循环遍历M个排序元素,得到每个国家在当前排序方式下的排名
6.按照规则处理输出,利用排序规则5恢复原来顺序,遍历每个国家元素选出该国家最佳排名的排名方式,及其排名,按规则依次输出。