【PAT】【排序】1012 The Best Rank

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <map>
#include <set>
#include <cmath>
using namespace std;

//总结:做题思路要清晰,不能急,不然可能反而走弯路更慢
//第一种解法是自己写的都看不下去的傻瓜(智障)式做法
//开四个结构体数组,每个数组定义一个排序方式cmpa,排好序后将排名映射到map中,直接查询比较
const int maxn = 2e3 + 5;
struct node
{
    string id;
    int c, m, e, a;
}stu_a[maxn],stu_c[maxn],stu_m[maxn],stu_e[maxn];



//四种排序方式
bool comp_a(const node &lhs, const node &rhs)
{
    return lhs.a > rhs.a;
}
bool comp_c(const node &lhs, const node &rhs)
{
    return lhs.c > rhs.c;
}
bool comp_m(const node &lhs, const node &rhs)
{
    return lhs.m > rhs.m;
}
bool comp_e(const node &lhs, const node &rhs)
{
    return lhs.e > rhs.e;
}
//还开了个集合存放判断是否有这个学生 (铺张浪费很在行。。。)
set<string> s;
//四个映射
map<string, int> mpa, mpc, mpm, mpe;
int main()
{
    int n, q;
    cin >> n >> q;

    string t; int c, m, e, a;
    for(int i = 1; i <= n; i++)
    {
        cin >> t; s.insert(t);
        scanf("%d %d %d", &c, &m, &e);
        a = c + m + e;
        stu_e[i] = stu_m[i] = stu_c[i] = stu_a[i] = (node){t, c, m, e, a};
    }
    sort(stu_a + 1, stu_a + n + 1, comp_a);
    sort(stu_c + 1, stu_c + n + 1, comp_c);
    sort(stu_m + 1, stu_m + n + 1, comp_m);
    sort(stu_e + 1, stu_e + n + 1, comp_e);

//    建立映射,如果同分则排名应相同
    for(int i = 1; i <= n; i++)
    {
        if(stu_a[i - 1].a == stu_a[i].a && i != 1)
        mpa[stu_a[i].id] = mpa[stu_a[i - 1].id];
        else
        mpa[stu_a[i].id] = i;
    }
    for(int i = 1; i <= n; i++)
    {
        if(stu_c[i - 1].c == stu_c[i].c && i != 1)
        mpc[stu_c[i].id] = mpc[stu_c[i - 1].id];
        else
        mpc[stu_c[i].id] = i;
    }
    for(int i = 1; i <= n; i++)
    {
        if(stu_m[i - 1].m == stu_m[i].m && i != 1)
        mpm[stu_m[i].id] = mpm[stu_m[i - 1].id];
        else
        mpm[stu_m[i].id] = i;
    }
    for(int i = 1; i <= n; i++)
    {
        if(stu_e[i - 1].e == stu_e[i].e && i != 1)
        mpe[stu_e[i].id] = mpe[stu_e[i - 1].id];
        else
        mpe[stu_e[i].id] = i;
    }
//    查询比较,输出结果
    for(int i = 1; i<= q; i++)
    {
        cin >> t;
        if(s.count(t) != 1)
        {
            printf("N/A\n");
            continue;
        }
        char ans;
        int top = maxn;
        if(mpe[t] <= top)
        {
            ans = 'E';
            top = mpe[t];
        }
        if(mpm[t] <= top)
        {
            ans = 'M';
            top = mpm[t];
        }
        if(mpc[t] <= top)
        {
            ans = 'C';
            top = mpc[t];
        }
        if(mpa[t] <= top)
        {
            ans = 'A';
            top = mpa[t];
        }
        printf("%d %c\n", top, ans);
    }
    return 0;
}

 

//第二种做法
//比较好的做法应该是这样开结构体:
//这样直接开成数组可以省去下面非常多不必要的代码,也节省了非常多不必要的空间
struct student
{
//    四种成绩
    int grade[4];
//    相应排名
    int srank[4];
    string id;
}stu[maxn];

//这样定义比较函数则可以只写一遍,调用排序时直接for循环4次即可
int k = -1;
bool cmp(const student &lhs, const student &rhs)
{
    return lhs.grade[k] > rhs.grade[k];
}
//每次排序后将排名信息保存下来,要注意同分排名也相同
for(int i = 0; i < 4; i++)
for(int j = 1; j <= n; j++)
{
    if(stu[j].grade[i] == stu[j - 1].grade[i] && j != 1){
        // 和前一名分数相等, 并列排名
        stu[j].srank[i] = stu[j - 1].srank[i];
    }else{
        // 否则排名为j + 1
        stu[j].srank[i] = j;
    }
}

//排序之后,将位置信息分别映射到一个map中即可,因为四种排名都存放在结构体中了
map<string, int> mp;

for(int i = 1; i <= n; i++)
{
    mp[stu[i].id] = i;
}
//其它的根据这个思路做修改即可,另外set其实也是不必要的,map = 0时则不存在这个学生,因为没有第0名

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值