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