#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恢复原来顺序,遍历每个国家元素选出该国家最佳排名的排名方式,及其排名,按规则依次输出。

京公网安备 11010502036488号