zoukankan      html  css  js  c++  java
  • SGU 171 Sarov zones

    贪心算法

    原题链接:http://acm.sgu.ru/problem.php?contest=0&problem=171

    题目来源: http://acm.hust.edu.cn:8080/judge/contest/view.action?cid=11221#problem/B

    CSUST-2012年暑假-8月11日,组队后第5场个人训练赛

    第一次中奖题目,感谢kb神的代码。。。

    一个多月后重做。

    171. Sarov zones

    time limit per test: 0.5 sec.
    memory limit per test: 4096 KB
    input: standard
    output: standard



    It is known that to participate the All-Russian Mathematic Olympiad one should do one of other olympiads enough good. These olympiads are called "zone olympiads" and the region from which people participate the same zone olympiad is called "zone". Sarov city of Nizhny Novgorod district is situated near the boundary of zones, so every year school students of Sarov participate several zones. 

    This year K zones invited students from Sarov to participate their olympiads. i-th zone invited N[i] students, so N=N[1]+N[2]+...+N[K] totally students were invited. After the Sarov city olympiad, N students were selected, so now the olympiad authorities of Sarov have to decide, which students will participate which zone olympiad. Each student is characterized by his olympiad level and each zone is characterized by its zone level. If a student with olympiad level P participates zone with zone level Q, he will be invited to All-Russian olympiad if and only if P>Q. 

    Every student is also characterized by his "weight". The Sarov olympiad authorities want, that the All-Russian Olympiad will be participated by students with maximal summary weight. You are to help them. Write a program which will divide the students between zones. Keep in mind that exactly N[i] students can go to i-th zone.

    Input
    On the first line of input there is an only integer K (1<=K<=100). On the second line there are K integers N[1], N[2], ... ,N[K] (0<=N[i]<=16000). On the third line there are K more integers Q[1], Q[2], ... ,Q[K] --- the zone levels of the zones. On the fourth line there are N integers P[1], P[2], ... P[N] --- olympiad levels of the students. (0<=Q[i]<=1000000, 0<=P[i]<=1000000). On the last (and fifth) line there are N integers w[1], w[2], ... w[k] --- the "weights" of students. 0<=w[i]<=100000. It is also guaranteed that 0<=N<=16000.

    Output
    Output only N integers --- Z[1], Z[2], ... Z[N] --- the numbers of zones which should be participated by students 1, 2, ... N.

    Sample test(s)

    Input
    
    
    2 1 1 4 1 2 3 2 1
    Output
    
    
    2 1

    题目大意:

    有K个区域要在一个学校选拔学生去参加奥赛。
    样例的第一行就是输入的区域个数。
    每个区域有各自的限定名额,和进入的分数线,即题目中的zone level Q。给你要参赛的人的成绩和体重,让你把他们分别分到各个区域。
    那么样例的第二行就有K个数,分别代表第一到第K个区域限定要选的名额。
    样例的第三行也有K个数,分别对应进入相应区域的分数线Q(难度系数)。
    样例第四行,各个学生的成绩。
    样例第五行,对应的学生的体重。
    分配好学生,并且输出各个区域参赛的学生编号。

    关于输出:是按照输入时的学生顺序依次输出他们所在赛区的编号。

    叶:可类比于高考的录取,先划分录取,如果没有录满,则降分录取(即对于没有进入赛区的同学随机分配)。

    算法:贪心、sort()排序。

    分析:

    可以将区域按级别排序 ,从高到低依次处理。能够达到高级别区域的学生就放进去,一旦都达到了分数线,如果学生有多余,则优先考虑体重大的(学生体重从大到小排序),因为题目中奥组委要求的是希望各自的区域的选手,体重尽可能的大,所以处理当前级别时,一定优先考虑体重大的。最后剩下没有放入任何区域的学生属于不起作用的,随机放入还有名额空闲的区域即可。 

    两个排序:

    1、先对区域的录取分数排序,当然是择优录取,但是因为每个学生都必须要有地方比赛、所以先对区域的分数由大到小排序。
    2、再对学生排序,学生的特征有两点一个是成绩,另一个是体重。因为题目要求的是各奥组委希望自己赛区的选手的体重尽量的大,所以先考虑学生的体重,按照体重从大到小排序,再按照成绩的由小到大排序。如果体重相同(但是数据中好像没有涉及到体重相同的情况,没考虑这个,代码也A了,奇怪的题目。),则先考虑p小的,毕竟还是尽量让每个学生都达到录取线,而p大的话,选择的机会也大,所以体重相同是优先考虑p小的,当然这一点对于AC貌似没有关系。 

    重做的代码:

    //Accepted	1139 KB	46 ms	Visual Studio 8 C++	1338 B	2012-09-22 15:44:41
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int MAXK=100+10;
    const int MAXN=16000+10;
    struct Zone
    {
        int index;//编号
        int N;//需要的人数
        int Q;//进入该区域的分数线
    }zone[MAXK];
    struct Stu
    {
        int index;//编号
        int P;//水平
        int w;//重量
    }stu[MAXN];
    int p[MAXN];
    bool cmp1(Zone a,Zone b)//按照Q从大到小排序
    {
        return a.Q>b.Q;
    }
    bool cmp2(Stu a,Stu b)//按照w从大到小排序
    {
        return a.w>b.w;
    }
    int main()
    {
        int k;
        int i,j;
        int num=0;
        scanf("%d",&k);
         
        for(i=0;i<k;i++)
        {
            zone[i].index=i+1;
            scanf("%d",&zone[i].N);
            num+=zone[i].N;
        }
        for(i=0;i<k;i++)
            scanf("%d",&zone[i].Q);
        sort(zone,zone+k,cmp1);
        for(i=0;i<num;i++)
        {
            stu[i].index=i+1;
            scanf("%d",&stu[i].P);
        }
        for(i=0;i<num;i++)
            scanf("%d",&stu[i].w);
        sort(stu,stu+num,cmp2);
        memset(p,-1,sizeof(p));
        for(i=0;i<num;i++)//第一轮先分配成绩达到了的
        {
            for(j=0;j<k;j++)
            {
                if(stu[i].P>zone[j].Q && zone[j].N)//注意:是stu[i].P>zone[j].Q不是>=
                {
                    p[stu[i].index]=zone[j].index;
                    zone[j].N--;
                    break;//依次对排好序的学生逐个从排好序的区域逐个安排
                }//也就是说对下一个学生也从第一个区域开始排
            }
        }
        j=0;
        for(i=0;i<num;i++)//分配剩下的人
        {
            if(p[i+1]!=-1)
               continue;//表示已经分配
            while(zone[j].N==0)
               j++;//表示当前区域已经招满
            p[i+1]=zone[j].index;
            zone[j].N--;
        }
        for(i=1;i<=num;i++)
        printf("%d ",p[i]);
        return 0;
    }
    


  • 相关阅读:
    strcpy和memcpy的区别(转)
    获得discuz7.2 目录下所有文件,并写到txt
    Lintcode: Majority Number 解题报告
    Lintcode: Fast Power 解题报告
    LeetCode: Pow(x, n) 解题报告
    Lintcode: Minimum Subarray 解题报告
    Lintcode: Subarray Sum 解题报告
    LeetCode: Minimum Depth of Binary Tree 解题报告
    LeetCode: Binary Tree Maximum Path Sum 解题报告
    LeetCode: Binary Tree Postorder Traversal 解题报告
  • 原文地址:https://www.cnblogs.com/freezhan/p/2776477.html
Copyright © 2011-2022 走看看