XDOJ 472 奥运奖牌榜

题面

问题描述

  给定多个比赛项目的不同国家和地区代表队运动员成绩,总结奥运奖牌榜。请编写一个函数AdjustSortTable,将奖牌榜按照规定的规则进行重新排序。函数声明如下:

void AdjustSortTable(int aSortTable[],struct medalCountry aMedalCountry[], int iCounter, int iNo, int iMedalType);

返回值:

参数:

AdjustSortTable:输入/输出参数,输入表示待重排数组,输出表示重排序后的数组

aMedalCountry:表示当前奖牌数目刚刚发生变化的代表队

iCounter:表示当前奖牌榜上总共有的代表队数目

iNo:表示当前奖牌数目刚刚发生变化的代表队目前在奖牌榜中的位置序号

iMedalType:表示当前奖牌数目刚刚发生变化的代表队刚刚获得的奖牌类型,其值为GOLDMEDAL(值0)代表金牌,SILVERMEDAL(值1)代表银牌,BRONZEMEDAL(值2)代表铜牌。

注意:函数声明已包含在主程序中,不需要自己定义。只需要提交自定义的函数代码。

主程序如下:

#include <stdio.h>
#include <string.h>

struct medalCountry{
    int iPlace;
    char sName[3];
    int iMedalNum[3];
};

enum medalType{ GOLDMEDAL , SILVERMEDAL, BRONZEMEDAL};


void AdjustSortTable(int aSortTable[],struct medalCountry aMedalCountry[], int iCounter, int iNo, int iMedalType);

int main(void)
{
    int n,i,j,counter=0;
    struct medalCountry aMedalCountry[206]={0};
    struct medalCountry *pSMC;
    int aSortTable[206];
    char sNameTmp[3];
    scanf("%d",&n);
    for(i=0; i<n; i++)
    {
        //Gold Medal
        scanf("%s",sNameTmp);
        for(j=0; j<counter;j++)
        {
            if(!strcmp(aMedalCountry[j].sName, sNameTmp))
            {
                aMedalCountry[j].iMedalNum[GOLDMEDAL]++;
                AdjustSortTable(aSortTable, aMedalCountry, counter, j, GOLDMEDAL);
                break;
            }
        }
        if(j==counter)
        {
            strcpy(aMedalCountry[j].sName, sNameTmp);
            aMedalCountry[j].iMedalNum[GOLDMEDAL]++;
            aSortTable[j]=j;
            counter++;
            AdjustSortTable(aSortTable, aMedalCountry, counter, j, GOLDMEDAL);
        }

        //Silver Medal
        scanf("%s",sNameTmp);
        for(j=0; j<counter;j++)
        {
            if(!strcmp(aMedalCountry[j].sName, sNameTmp))
            {
                aMedalCountry[j].iMedalNum[SILVERMEDAL]++;
                AdjustSortTable(aSortTable, aMedalCountry, counter, j, SILVERMEDAL);
                break;
            }
        }
        if(j==counter)
        {
            strcpy(aMedalCountry[j].sName, sNameTmp);
            aMedalCountry[j].iMedalNum[SILVERMEDAL]++;
            aSortTable[j]=j;
            counter++;
            AdjustSortTable(aSortTable, aMedalCountry, counter, j, SILVERMEDAL);
        }

        //Bronze Medal
        scanf("%s",sNameTmp);
        for(j=0; j<counter;j++)
        {
            if(!strcmp(aMedalCountry[j].sName, sNameTmp))
            {
                aMedalCountry[j].iMedalNum[BRONZEMEDAL]++;
                AdjustSortTable(aSortTable, aMedalCountry, counter, j, BRONZEMEDAL);
                break;
            }
        }
        if(j==counter)
        {
            strcpy(aMedalCountry[j].sName, sNameTmp);
            aMedalCountry[j].iMedalNum[BRONZEMEDAL]++;
            aSortTable[j]=j;
            counter++;
            AdjustSortTable(aSortTable, aMedalCountry, counter, j, BRONZEMEDAL);
        }
    }

    for(i=0; i<counter; i++)
    {
        aMedalCountry[aSortTable[i]].iPlace = i;
        pSMC=aMedalCountry+aSortTable[i];
        printf("%3d %3s %3d %3d %3d\n", pSMC->iPlace+1, pSMC->sName, pSMC->iMedalNum[GOLDMEDAL], pSMC->iMedalNum[SILVERMEDAL], pSMC->iMedalNum[BRONZEMEDAL]);
    }

    return 0;
}

主函数输入格式

  输入的第一行包含一个整数n,表示给出了n个比赛项目的前三名所属代表队信息。

  第二行起的n行给出了n个比赛项目的金银铜牌运动员所属代表队信息,每行包含3个字符a1, a2, a3,表示金银铜牌运动员所属代表队代号,相邻的代号之间用一个空格分隔。

主函数输出格式

  输出优先按照金牌数,金牌数相同的按照银牌数,金银牌数目都相同的按照铜牌数从多到少,金银铜牌都相同的按照代号字母顺序排出的奥运奖牌棒。每个国家输出一行,每行包括名次、代表队代号、金牌数、银牌数、铜牌数信息,每项信息占用3个字符长度。

样例输入

8

A B C

C C A

D B C

A D E

A C F

I G H

A D C

C B F

样例输出

   1   A   4   0   1

   2   C   2   2   3

   3   D   1   2   0

   4   I   1   0   0

   5   B   0   3   0

   6   G   0   1   0

   7   F   0   0   2

   8   E   0   0   1

   9   H   0   0   1

样例说明

  在给出的8个项目中,A有4项拿到了金牌,所以排位第1位;D、I的金牌数相同,按银牌数排序,D在I前;E、H的金银铜牌个数均相同,E的字母顺序在H前,因此E排在前。

评测用例规模与约定

1 ≤ n ≤ 303,每个代表队用一个或两个字母代替,总代表队数小于等于206个。

题解 

变量的含义

  1. 结构体

    • struct medalCountry: 用于表示每个国家在奖牌榜上的信息。
      • iPlace: 该国家的排名。
      • sName[3]: 该国家的名称(由于大小为3,可能只适合2字符的国家代码加上结束符'\0')。
      • iMedalNum[3]: 该国家获得的金、银、铜奖牌数量。
  2. 枚举

    • enum medalType: 用于表示奖牌的类型。
      • GOLDMEDAL: 金牌。
      • SILVERMEDAL: 银牌。
      • BRONZEMEDAL: 铜牌。
  3. 主函数中

    • i, j, counter: 循环计数器和当前已输入的国家数量。
    • aMedalCountry[206]: 存储最多206个国家的奖牌信息。
    • pSMC: 指向aMedalCountry中某个不定元素的指针。
    • aSortTable[206]: 存储aMedalCountry的索引,用于排序。
    • sNameTmp[3]: 临时存储输入的国家名称。 

主函数逻辑

输入一个国家,处理一个国家
如果是已有国家,那就将这个国家对应的奖牌数加一,并排序;
如果是新的国家代号,则就记录这个国家并且将计数器counter加一,排一次序。

函数

根据已有国家数目(iCounter),根据题目中给出的规则对aSortTable[]进行排序

这题有趣的是,我直接使用最暴力的方法,每次都全部排一边,程序没有问题。

代码 

void AdjustSortTable(int aSortTable[], struct medalCountry aMedalCountry[], int iCounter, int iNo, int iMedalType) {  
    int i, j, temp;
      
    // 调整奖牌榜的索引数组aSortTable  
    // 使用冒泡排序 
    for (j = 0; j < iCounter - 1; j++)
    	for (i = 0; i < iCounter - j - 1; i++)
		{
    		if(
				aMedalCountry[aSortTable[i + 1]].iMedalNum[GOLDMEDAL] > aMedalCountry[aSortTable[i]].iMedalNum[GOLDMEDAL] ||
        		(aMedalCountry[aSortTable[i + 1]].iMedalNum[GOLDMEDAL] == aMedalCountry[aSortTable[i]].iMedalNum[GOLDMEDAL] &&
        		(aMedalCountry[aSortTable[i + 1]].iMedalNum[SILVERMEDAL] > aMedalCountry[aSortTable[i]].iMedalNum[SILVERMEDAL] ||
        		(aMedalCountry[aSortTable[i + 1]].iMedalNum[SILVERMEDAL] == aMedalCountry[aSortTable[i]].iMedalNum[SILVERMEDAL] &&
        		(aMedalCountry[aSortTable[i + 1]].iMedalNum[BRONZEMEDAL] > aMedalCountry[aSortTable[i]].iMedalNum[BRONZEMEDAL] ||
        		(aMedalCountry[aSortTable[i + 1]].iMedalNum[BRONZEMEDAL] == aMedalCountry[aSortTable[i]].iMedalNum[BRONZEMEDAL] &&
        		strcmp(aMedalCountry[aSortTable[i + 1]].sName, aMedalCountry[aSortTable[i]].sName) < 0)))))
				) // 又臭又长的判断 
    		{
    			temp = aSortTable[i + 1];  
       	 		aSortTable[i + 1] = aSortTable[i];  
        		aSortTable[i] = temp;
			}  
    }  
}

感想

函数题对我来说不难,
关键是我在看题目的时候已经想到了更好的解决方案,
但是得按照题目的思路往下想。

date:20231231 

  • 21
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

bbw20110110

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值