pat 甲级 1012 The Best Rank

这道题的思路是算出平均分,然后分别对平均分、c语言、数学、英语进行排序。当用student ID查询时,根据对应分数查询四个分数的名次,输出最优的名次。下面将问题拆分:

1.首先是求出平均分,t[1~3]分别对应c语言、数学、英语的分数。t[0]为总分。利用math自带的round()函数对(总分/3.0)进行四舍五入得到平均分。

int t[4]={0};
for(int j=1;j<4;j++){
    cin>>t[j];
    t[0]+=t[j];
}
t[0]=round(t[0]/3.0);//除以3.0得到的结果为浮点数。

2.(1)因为总共4个分数,但是人数不确定,考虑使用可变长数组vector<int> g[4]存储分数。

(2)因为要根据student ID 查询最优的名次。需要一对一的对应关系,考虑使用map。unordered_map<string,vector<int>> grades

代码如下:

unordered_map<string,vector<int>> grades;
vector<int> g[4];
for(int j=0;j<4;j++){
     g[j].push_back(t[j]);//g[0]存放的是所有人的平均分,g[1]为所有人的c语言,依次类推;
     grades[id].push_back(t[j]);//grades[id]存放的是studet ID为id的学生的四个成绩;
}
for(int i=0;i<4;i++)    
    sort(g[i].begin(),g[i].end(),greater<int>());//对学生的四个成绩进行从大到小的排序;

3.给出student ID如何查询最优的名次?

根据student ID从map中得到对应的四个分数,依次查询该分数在vector<int>中的位置(即排名),得到最优的名次。那么如何查询位置呢。可以顺序遍历vector看看是否相等。也可以使用二分。这里使用二分。代码如下:

int get(vector<int>&a,int x){//a即所有人的某个分数降序序列,x为某个人的分数;
    int l=0,r=a.size()-1;
    while(l<r){
        int mid=(l+r)>>1;
        if(x>=a[mid]) r=mid; 
        else l=mid+1;
    }
    return l+1; //因为vector从0开始,但是排名从1开始,所以需要+1;
}

整合代码如下:

#include<iostream>
#include<algorithm>
#include<string>
#include<vector>
#include<unordered_map>
#include<cmath>

using namespace std;
unordered_map<string,vector<int>> grades;
vector<int> g[4];
int get(vector<int>& a,int x){
    int l=0,r=a.size()-1;
    while(l<r){
        int mid=(l+r)>>1;
        if(x>=a[mid]) r=mid;
        else l=mid+1;
    }
    return l+1; 
}

int main()
{
    int n,m;
    cin>>n>>m;
    for(int i=0;i<n;i++){
        string id;
        cin>>id;
        int t[4]={0};
        for(int j=1;j<4;j++){
            cin>>t[j];
            t[0]+=t[j];
        }
        t[0]=round(t[0]/3.0);//除以3.0得到的结果是浮点数
        for(int j=0;j<4;j++){
             g[j].push_back(t[j]);//g[0]存放的是所有人的平均分,g[1]为所有人的c语言,依次类推;
             grades[id].push_back(t[j]);//grades[id]存放的是studet ID为id的学生的四个成绩;
        }
    }
    for(int i=0;i<4;i++)    sort(g[i].begin(),g[i].end(),greater<int>()); //依次对所有人的某个成绩进行降序排列
    char name[]="ACME";
    while(m--){
        string id;
        cin>>id;
        if(grades.count(id)==0)    puts("N/A");//如果map没有该id,则这个人不存在
        else{
            int res=n+1; 
            char c;
            for(int i=0;i<4;i++){
                int rank=get(g[i],grades[id][i]);//g[i]为某科所有人的成绩,grades[id][i]为student ID为id的学生的某科的成绩,进行二分查找,找到对应的排名。
                if(rank<res){
                    res=rank; 
                    c=name[i];
                }
            }
            cout<<res<<" "<<c<<endl;
        }
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值