PAT-A 1055. The World's Richest (25)

题目链接在此

题意

给定N个人的信息(姓名、年龄、财富值),然后进行K次查询,每次查询要求输出年龄在[amin,amax]之间的财富值从小到大的前M个人的信息。如果财富值相同,则按照年龄从小到大排序,年龄相同则按照名字的字典序排序。

思路及代码

思路1

首先根据年龄排序,然后根据输入的amin和amax,找到这个区间内的人,然后对这个区间内的人再按照输出的要求排序。
这种思路会有两个测试点超时。

然后为了减少使用sort函数,使用一个temp结构体数组,用来保存按照年龄排序的结果,这样就可以少用sort数组去根据年龄排序,只需要在temp和richer数组赋值操作即可,这样做仍然有一个测试点超时。

思路1代码

两个测试点超时的代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>

using namespace std;

struct INFO{
    char name[9];
    int age;
    int wealth;
}richer[100001];

//sort by age
bool cmp_age(INFO a, INFO b){
    return a.age < b.age;
} 

//sort for final rules
bool cmp(INFO a, INFO b){
    if(a.wealth != b.wealth) return a.wealth > b.wealth;
    else if(a.age != b.age) return a.age < b.age;
    else return (strcmp(a.name, b.name ) <0 );
}

bool cmp_test(INFO a, INFO b){
    return a.wealth < b.wealth;
}

int main(){

    int N,K,M;
    scanf("%d %d",&N, &K);
    getchar(); //吸收换行 

    for(int i = 0; i < N; i++){
        scanf("%s %d %d",&richer[i].name, &richer[i].age, &richer[i].wealth);
    } 

    //get K queries & get result
    int C, amin, amax; //保存K个查询的信息 
    for(int i = 0 ; i < K; i++){

        sort(richer, richer+N, cmp_age);

        scanf("%d",&C);
        scanf("%d",&amin);
        scanf("%d",&amax);

        //find richers whose age in [amin,amax]
        int start;
        for(start = 0; start < N; start++){
            if(richer[start].age >= amin){
                break;
            }
        }

        int end;
        for(end = start; end < N; end++){
            if(richer[end].age > amax){
                break;  
            }
        }

        sort(richer+start, richer+end, cmp);

        printf("Case #%d:\n",i+1);
        if(start == end){
            printf("None\n");
        }else{

            if(C > (end-start)){ //比如数据中只有3个,而需要打印前4 的情况 
                C = end-start;
            }

            //print the results
            for(int j = start; j < start+C; j++){
                printf("%s %d %d\n",richer[j].name, richer[j].age, richer[j].wealth);
            }   
        }

    }

    return 0;
}

一个测试点超时的代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>

using namespace std;

struct INFO{
    char name[9];
    int age;
    int wealth;
//  bool flag;
}richer[100001],temp[100001];

//sort by age
bool cmp_age(INFO a, INFO b){
    return a.age < b.age;
} 

//sort for final rules
bool cmp(INFO a, INFO b){
    if(a.wealth != b.wealth) return a.wealth > b.wealth;
    else if(a.age != b.age) return a.age < b.age;
    else return (strcmp(a.name, b.name ) <0 );
}

bool cmp_test(INFO a, INFO b){
    return a.wealth < b.wealth;
}

// temp to richer
void tempToRicher(int N){
    for(int i = 0; i < N; i++){
        richer[i] = temp[i];
    }
}

int main(){

    int N,K,M;
    scanf("%d %d",&N, &K);
    getchar(); //吸收换行 

    for(int i = 0; i < N; i++){
        scanf("%s %d %d",&richer[i].name, &richer[i].age, &richer[i].wealth);
    } 

    //sort by age
    sort(richer, richer+N, cmp_age);
    //put ordered richer to temp
    for(int i = 0; i < N; i++){
        temp[i] = richer[i];
    }

    //get K queries & get result
    int C, amin, amax; //保存K个查询的信息 
    for(int i = 0 ; i < K; i++){

//      sort(richer, richer+N, cmp_age);

        scanf("%d",&C);
        scanf("%d",&amin);
        scanf("%d",&amax);

        //find richers whose age in [amin,amax]
        int start;
        for(start = 0; start < N; start++){
            if(richer[start].age >= amin){
                break;
            }
        }

        int end;
        for(end = start; end < N; end++){
            if(richer[end].age > amax){
                break;  
            }
        }

        sort(richer+start, richer+end, cmp);

        printf("Case #%d:\n",i+1);
        if(start == end){
            printf("None\n");
        }else{

            if(C > (end-start)){ //比如数据中只有3个,而需要打印前4 的情况 
                C = end-start;
            }

            //print the results
            for(int j = start; j < start+C; j++){
                printf("%s %d %d\n",richer[j].name, richer[j].age, richer[j].wealth);
            }   
        }

        tempToRicher(N);
    }

    return 0;
}

思路2

既然是因为查找元素过多而超时的,那么就应该减少查找元素堆的规模。这里由于M<=100,所以将每个年龄中财富在前100名的人的信息存放在一个数组中,输出的时候到这个数组中去取即可。

思路2代码

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>

using namespace std;

struct INFO{
    char name[9];
    int age;
    int wealth;
//  bool flag;
}richer[100001],valid[100001]; //valid 保存每个年龄前100人的信息

//sort for final rules
bool cmp(INFO a, INFO b){
    if(a.wealth != b.wealth) return a.wealth > b.wealth;
    else if(a.age != b.age) return a.age < b.age;
    else return (strcmp(a.name, b.name ) <0 );
}

bool cmp_test(INFO a, INFO b){
    return a.wealth < b.wealth;
}

int main(){

    int N,K,M;
    scanf("%d %d",&N, &K);
    getchar(); //吸收换行 

    for(int i = 0; i < N; i++){
        scanf("%s %d %d",&richer[i].name, &richer[i].age, &richer[i].wealth);
    } 

    //sort by age
    sort(richer, richer+N, cmp);

    //将每个年龄排名前100的人的信息放到一个数组中,提高查找效率 
    int num[210] = {0}; //保存每个年龄的人数

    int many = 0; //保存valid数组的大小 
    for(int i = 0; i < N; i++){
        if(num[richer[i].age] < 100) { //年龄为richer[i].age的人数小于100人时 
            valid[many++] = richer[i]; //将richer[i]加入数组中 
            num[richer[i].age]++; // 年龄为richer[i].age的人数+1
        }
    } 

    //get K queries & get result
    int C, amin, amax; //保存K个查询的信息 
    for(int i = 0 ; i < K; i++){

        scanf("%d",&C);
        scanf("%d",&amin);
        scanf("%d",&amax);

        printf("Case #%d:\n",i+1);
        int count = 0; //已经输出的人数 
        for(int j = 0; j < many && count<C; j++){
            if(valid[j].age>=amin && valid[j].age<=amax){
                printf("%s %d %d\n",valid[j].name, valid[j].age, valid[j].wealth);
                count++;
            }
        } 

        if(count == 0){
            printf("None\n");
        }

    }

    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值