zoukankan      html  css  js  c++  java
  • PAT甲级1055The World's Richest

    题目介绍

    • 题目链接

      https://pintia.cn/problem-sets/994805342720868352/problems/994805421066272768

    • 题目考点

      排序,重点在时间复杂度优化上

    • 题目难度

      PAT甲级25分

    • 题目大意

      给出N个人,请找出指定年龄范围内最有钱的M个人、

    • 输入

      • N:正整数,不超过100000,人的数量
      • K:正整数,不超过1000,查询的数量
      • N个人:每行包括名字(不包含空格、最多8个字符的字符串)、年龄(范围(0,200])、净值(范围为±1e6)
      • K次查询:M(筛选最有钱的几个人,不超过100)、年龄范围[Amin,Amax]
    • 输出

      对于每1个查询,输出是第几个查询(从1到K),然后按净值非增序输出指定年龄范围内最有钱的M个人的信息,如果有重复则按年龄非降序输出,如果还有重复则按名字非降序输出。如果指定年龄范围内没人,就输出None

    题解一

    解题思路

    • 关于指定年龄范围,只要在输出时进行年龄判断即可。

      也可以考虑在结构体比较函数中进行年龄判断,当有不符合年龄限制的人时,将其往后放。

    • 关于最有钱的人的数量,排序后只输出前M个符合年龄范围的人即可。

    • 用这个思路,测试点1和2会超时,因为这个算法的时间复杂度为(O(kcdot n)),最大为1e8(耗时约1秒)。

      M最大值为100,N最大值为100000,N和M差距很大,在N个人中寻找符合条件的M个人非常耗时。

    代码

    // Problem: PAT Advanced 1055
    // URL: https://pintia.cn/problem-sets/994805342720868352/problems/994805421066272768
    // Tags: 排序
    
    #include <iostream>
    #include <string>
    #include <vector>
    #include <algorithm>
    using namespace std;
    
    int ageMin, ageMax;
    
    struct Person{
        string name;
        int age, wealth;
    };
    
    bool personCmp(Person& p1, Person& p2){
        if (p1.age<ageMin || p1.age>ageMax)
            return false;
        if (p2.age<ageMin || p2.age>ageMax)
            return true;
        if (p1.wealth == p2.wealth){
            if (p1.age == p2.age)
                return p1.name < p2.name;
            else
                return p1.age < p2.age;
        }
        else
            return p1.wealth > p2.wealth;
    }
    
    int main()
    {
        int n,k;
        scanf("%d %d", &n, &k);
        vector<Person> people(n);
        for(int i=0; i<n; i++)
            cin >> people[i].name >> people[i].age >> people[i].wealth;
        for (int x=1, m; x<=k; x++){
            scanf("%d%d%d", &m, &ageMin, &ageMax);
            sort(people.begin(), people.end(), personCmp);
            printf("Case #%d:
    ", x);
            
            int count=0;
            for(int i=0; i<n && count<m; i++)
                if (people[i].age>=ageMin && people[i].age<=ageMax){
                    printf("%s %d %d
    ", people[i].name.c_str(), people[i].age, people[i].wealth);
                    count++;
                }
            if (count==0)
                printf("None
    ");
        }
        return 0;
    }
    

    题解二

    解题思路

    • 年龄范围是(0,200],每次最多找100个人(M不超过100),那我们取出每个年龄的前100名,这样最多有20000个人。在这20000个人中查找M个人,还是快的(时间复杂度从题解一的1e8到现在的2e7),就不会超时了。

    代码

    // Problem: PAT Advanced 1055
    // URL: https://pintia.cn/problem-sets/994805342720868352/problems/994805421066272768
    // Tags: 排序
    
    #include <iostream>
    #include <string>
    #include <vector>
    #include <algorithm>
    using namespace std;
    
    int ageMin, ageMax;
    
    struct Person{
        string name;
        int age, wealth;
    };
    
    bool personCmp(Person& p1, Person& p2){
        if (p1.wealth == p2.wealth){
            if (p1.age == p2.age)
                return p1.name < p2.name;
            else
                return p1.age < p2.age;
        }
        else
            return p1.wealth > p2.wealth;
    }
    
    int main()
    {
        int n,k, selectedNum[201]={0};
        scanf("%d %d", &n, &k);
        vector<Person> people(n), selectedPeople;
        for(int i=0; i<n; i++)
            cin >> people[i].name >> people[i].age >> people[i].wealth;
        sort(people.begin(), people.end(), personCmp);
        for(int i=0; i<n; i++)
            if (selectedNum[people[i].age] < 100){
                selectedPeople.push_back(people[i]);
                selectedNum[people[i].age]++;
            }
        for (int x=1, m; x<=k; x++){
            scanf("%d%d%d", &m, &ageMin, &ageMax);
            printf("Case #%d:
    ", x);
            
            int count=0;
            for(int i=0; i<selectedPeople.size() && count<m; i++)
                if (selectedPeople[i].age>=ageMin && selectedPeople[i].age<=ageMax){
                    printf("%s %d %d
    ", selectedPeople[i].name.c_str(), selectedPeople[i].age, selectedPeople[i].wealth);
                    count++;
                }
            if (count==0)
                printf("None
    ");
        }
        return 0;
    }
    

    参考链接


    Github(github.com):@chouxianyu

    Github Pages(github.io):@臭咸鱼

    知乎(zhihu.com):@臭咸鱼

    博客园(cnblogs.com):@臭咸鱼

    B站(bilibili.com):@绝版臭咸鱼

    微信公众号:@臭咸鱼

    转载请注明出处,欢迎讨论和交流!


  • 相关阅读:
    docker镜像管理基础
    docker的基础应用
    mysql基础
    策略模式
    简单工厂模式
    hystrix-go简介
    手把手带你使用 go-kit(option)
    手把手带你使用 go-kit(组件扩充,服务发现)
    手把手带你使用 go-kit(客户端直连)
    手把手带你使用 go-kit(基础篇)
  • 原文地址:https://www.cnblogs.com/chouxianyu/p/14379508.html
Copyright © 2011-2022 走看看