hdu 3789 奥运排序问题

奥运排序问题

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
开始把题意理解错了。做出了自己理解错了的一道题。题目只要求排给出的m个国家的排名而不是全部国家的排名。还有要注意按输入顺序输出m个国家的最佳排名。
不想用库函数。自己写的改版的二叉排序树。
#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];//存入每个国家的四种排名
typedef struct
{
    int sg,sp;
    double pp;
} ct;
void btree(int *root,int *c,team *sorts,double data)//根据data的值来排序
{
    int now;//记录当前位置
    if(*root==-1)
    {
        *root=*c;//分配空间
        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()
{
    ct city[5000];
    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);//读入数据用四种方式排序
            city[i].sg=sg;
            city[i].sp=sp;
            city[i].pp=pp;
        }
        for(i=0;i<m;i++)
            scanf("%d",&num[i]);//存入需排序国家号
        for(i=0;i<m;i++)
        {
            btree(&root1,&q,sort1,(double)city[num[i]].sg);
            btree(&root2,&w,sort2,(double)city[num[i]].sp);
            btree(&root3,&e,sort3,city[num[i]].sg/city[num[i]].pp);
            btree(&root4,&r,sort4,city[num[i]].sp/city[num[i]].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++)
        {
            ans=0;
            for(j=0;j<4;j++)//找出最佳排序名次和方式
            {
                if(ranks[i][j]<ranks[i][ans])
                    ans=j;
            }
            printf("%d:%d\n",ranks[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
一同学的思想感觉很经典于是给他代码实现了。没有了繁琐的排序。给排位问题提供了新的思路。
不过要用g++提交才行c++就是错的。不知道为什么。可能对浮点数处理不一样吧。
#include <stdio.h>

struct country
{
    double value[4];//分别代表金牌数。奖牌数。金牌人口比列。奖牌人口比列
    int rk[4];//分别代表四种排名方式
} ct[10000];//代表国家
int wrk[10000];
int main()
{
    int n,m,i,j,k,a,b,ans;
    double p;

    while(~scanf("%d%d",&n,&m))
    {
        for(i=0; i<n; i++)
        {
            scanf("%lf%lf%lf",&ct[i].value[0],&ct[i].value[1],&p);
            ct[i].value[2]=ct[i].value[0]/p;//金牌人均总数
            ct[i].value[3]=ct[i].value[1]/p;//奖牌人均总数
            ct[i].rk[0]=ct[i].rk[1]=ct[i].rk[2]=ct[i].rk[3]=1;//初始排名都为1
        }
        for(i=0; i<m; i++)//记录待排名的国家号
            scanf("%d",&wrk[i]);
        for(i=0;i<m;i++)//利用排名原理。感觉很经典。排名数就是比你优秀的人数加1(优秀标准由题目给出)
        {
            a=wrk[i];
            for(j=0;j<m;j++)
            {
                b=wrk[j];
                for(k=0;k<4;k++)
                {
                    if(ct[a].value[k]<ct[b].value[k])
                        ct[a].rk[k]++;
                }
            }
        }
        for(i=0; i<m; i++)
        {
            ans=0;
            a=wrk[i];
            for(j=0; j<4; j++)//记录最佳排名方式
                if(ct[a].rk[j]<ct[a].rk[ans])
                    ans=j;
            printf("%d:%d\n",ct[a].rk[ans],ans+1);
        }
        printf("\n");
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值