自己改编的一道acm题目。感觉思想不错。比较创新

奥运排序问题

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2331 Accepted Submission(s): 510


Problem Description
按要求,给国家进行排名。

Input
有多组数据。
第一行给出国家数N,要求输出所有国家排名最佳排名的国家数M,国家号从0到N-1。
第二行开始的N行给定国家或地区的奥运金牌数,奖牌数,人口数(百万)。
接下来一行给出M个国家号。

Output
排序有4种方式: 金牌总数 奖牌总数 金牌人口比例 奖牌人口比例
对每个国家给出最佳排名排名方式 和 最终排名
格式为: 排名:排名方式
如果有相同的最终排名,则输出排名方式最小的那种排名,对于排名方式,金牌总数 < 奖牌总数 < 金牌人口比例 < 奖牌人口比例
如果有并列排名的情况,即如果出现金牌总数为 100,90,90,80.则排名为1,2,2,4.
每组数据后加一个空行。

Sample Input
  
  
4 4 4 8 1 6 6 2 4 8 2 2 12 4 0 1 2 3 4 2 8 10 1 8 11 2 8 12 3 8 13 4 0 3

Sample Output
  
  
1:3 1:1 2:1 1:2 1:1 1:1

Source

Recommend
notonlysuccess
#include <stdio.h>

typedef struct
{
    double data;
    int left,right,down;
} team;
team sort1[5000],sort2[5000],sort3[5000],sort4[5000];//建四个二叉排序树
int q,w,e,r,rk;//用q,w,e,r来分配数组。记录下个可用的结构数组空间
int ranks[5000][4];//存入每个国家的四种排名
void btree(int *root,int *c,team *sorts,double data)//根据data的值来排序
{
    int now;//记录当前位置
    if(*root==-1)
    {
        *root=*c;//分配空间,可达到root等价于国家号的目的
        sorts[*root].data=data;
        sorts[*root].down=sorts[*root].left=sorts[*root].right=-1;
        (*c)++;//指向下个可用空间
    }
    else
    {
        now=*root;
        if(data<sorts[now].data)
            btree(&sorts[now].left,c,sorts,data);
        else if(data>sorts[now].data)
            btree(&sorts[now].right,c,sorts,data);
        else
            btree(&sorts[now].down,c,sorts,data);//如果相等就往下沉
    }
}
void saverank(int root,team *sorts,int way,int pa)//记录排名。way为排序方式
{//pa 为父亲的地址
    if(root==-1)
        return;//判断是否为空
    saverank(sorts[root].right,sorts,way,root);//先记录data较大国家排名
    if(pa!=-1&&sorts[root].data==sorts[pa].data)//如果data和父亲相等则
    //排名也相同。但rk还是要加。
        ranks[root][way]=ranks[pa][way],rk++;
    else
        ranks[root][way]=++rk;//不相等排名直接后挪
    saverank(sorts[root].down,sorts,way,root);//记录当前点一下。即data相等点排名
    saverank(sorts[root].left,sorts,way,root);//记录data较小的国家排名
}
int main()
{
    int i,j,n,m,sg,sp,num[5000],ans;//sg金牌数,sp奖牌数,num记录要排名的国家
    double pp;//记录人口数
    int root1,root2,root3,root4;//四个排序二叉树的根

    while(scanf("%d%d",&n,&m)!=EOF)
    {
        q=w=e=r=0;
        root1=root2=root3=root4=-1;//初始化
        for(i=0;i<n;i++)
        {
            scanf("%d%d%lf",&sg,&sp,&pp);//读入数据用四种方式排序
            btree(&root1,&q,sort1,(double)sg);
            btree(&root2,&w,sort2,(double)sp);
            btree(&root3,&e,sort3,sg/pp);
            btree(&root4,&r,sort4,sp/pp);
        }
        saverank(root1,sort1,0,-1),rk=0;//记录四种排序中国家的排名
        saverank(root2,sort2,1,-1),rk=0;
        saverank(root3,sort3,2,-1),rk=0;
        saverank(root4,sort4,3,-1),rk=0;
        for(i=0;i<m;i++)
            scanf("%d",&num[i]);//存入需排序国家号
        for(i=0;i<m;i++)
        {
            ans=0;
            for(j=0;j<4;j++)//找出最佳排序名次和方式
            {
                if(ranks[num[i]][j]<ranks[num[i]][ans])
                    ans=j;
            }
            printf("%d:%d\n",ranks[num[i]][ans],ans+1);
        }
        printf("\n");
    }
    return 0;
}
/*4 4
4 8 1
6 6 2
4 8 2
2 12 4
0 1 2 3
4 2
8 10 1
8 11 2
8 12 3
8 13 4
0 3
*///hdu 3789


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值