首页 > 试题广场 >

Graduate Admission (30)

[编程题]Graduate Admission (30)
  • 热度指数:4947 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 64M,其他语言128M
  • 算法知识视频讲解
It is said that in 2013, there were about 100 graduate schools ready to proceed over 40,000 applications in Zhejiang Province. It would help a lot if you could write a program to automate the admission procedure.
Each applicant will have to provide two grades: the national entrance exam grade GE , and the interview grade GI . The final grade of an applicant is (GE + GI ) / 2. The admission rules are:

  • The applicants are ranked according to their final grades, and will be admitted one by one from the top of the rank list.
  • If there is a tied final grade, the applicants will be ranked according to their national entrance exam grade GE. If still tied, their ranks must be the same.
  • Each applicant may have K choices and the admission will be done according to his/her choices: if according to the rank list, it is one's turn to be admitted; and if the quota of one's most preferred shcool is not exceeded, then one will be admitted to this school, or one's other choices will be considered one by one in order. If one gets rejected by all of preferred schools, then this unfortunate applicant will be rejected.
  • If there is a tied rank, and if the corresponding applicants are applying to the same school, then that school must admit all the applicants with the same rank, even if its quota will be exceeded.

  • 输入描述:
    Each input file contains one test case.  Each case starts with a line containing three positive integers: N (<=40,000), the total number of applicants; M (<=100), the total number of graduate schools; and K (<=5), the number of choices an applicant may have.
    In the next line, separated by a space, there are M positive integers. The i-th integer is the quota of the i-th graduate school respectively.
    Then N lines follow, each contains 2+K integers separated by a space. The first 2 integers are the applicant's GE and GI, respectively. The next K integers represent the preferred schools. For the sake of simplicity, we assume that the schools are numbered from 0 to M-1, and the applicants are numbered from 0 to N-1.


    输出描述:
    For each test case you should output the admission results for all the graduate schools.  The results of each school must occupy a line, which contains the applicants' numbers that school admits.  The numbers must be in increasing order and be separated by a space.  There must be no extra space at the end of each line.  If no applicant is admitted by a school, you must output an empty line correspondingly.
    示例1

    输入

    11 6 3
    2 1 2 2 2 3
    100 100 0 1 2
    60 60 2 3 5
    100 90 0 3 4
    90 100 1 2 0
    90 90 5 1 3
    80 90 1 0 2
    80 80 0 1 2
    80 80 0 1 2
    80 70 1 3 2
    70 80 1 2 3
    100 100 0 2 4

    输出

    0 10
    3
    5 6 7
    2 8
    
    1 4
    给个华丽丽的C#的玩法吧:

    “盲目”地使用Linq就可以非常轻松愉快地完成从主体数据输入到完成排序的任务,示例如下(nextInt是一个自己实现的函数,经试验,就算拿着记事本也是容易实现的)

            var kList = E.Range(0, k);
            var studentList = (
                from i in E.Range(0, n)
                let GE = nextInt()
                let GT = GE + nextInt()
                let APP = (
                    from j in kList
                    select nextInt()
                ).ToArray()
                orderby GT descending, GE descending
                select new { id = i, gt = GT, ge = GE, app = APP })
                .ToArray();

    但是这个方法不推荐使用,真心的……
    首先这里的nextInt()的执行顺序会有编译器优化导致被打乱的可能性(不相信你可以把orderby子句提前一下)
    其次Linq本身运行并不快,在zju的PAT官网,那个超级喜欢严格时限的地方,容易小幅度超时又无处争辩。
    (当然在这里,把读入部分用传统for循环来就不会超时了,排序继续愉快的Linq——注意到了吗,人家自己支持多关键词排序)

    如果感兴趣,Linq的高级用法请自己查询,以下是我在zju的官网上通过的代码(比较极限的卡了时间限制,不用Linq可以再宽松一点点):
    (另:这里的数据造的太随性了,所以Split方法还要加个参数:StringSplitOptions.RemoveEmptyEntries,不过浙大没这种数据多空格的糟糕习惯,有VS2010的考试场地你也不用背,intellisense会智能提示的)

    using System;
    using System.Text;
    using System.Collections.Generic;
    using E = System.Linq.Enumerable;
    using System.Linq;
    
    class Program {
        string[] tokens;
        int lastToken;
    
        int nextInt() {
            if (lastToken >= tokens.Length) {
                string tmp = Console.ReadLine();
                tokens = tmp.Split(new char[] { ' ' });
                lastToken = 0;
            }
            return int.Parse(tokens[lastToken++]);
        }
    
        Program() {
            tokens = new string[1];
            lastToken = 1;
    
            int n = nextInt(), m = nextInt(), k = nextInt();
    
            int[] maxAcc = new int[m];
            for (int i = 0; i < m; i++) maxAcc[i] = nextInt();
            List<int>[] schoolAccept = new List<int>[m];
            for (int i = 0; i < m; i++) schoolAccept[i] = new List<int>();
    
            int[] ge = new int[n];
            int[] gi = new int[n];
            int[][] appli = new int[n][];
            for (int i = 0; i < n; i++) {
                ge[i] = nextInt();
                gi[i] = nextInt();
                appli[i] = new int[k];
                for (int j = 0; j < k; j++) appli[i][j] = nextInt();
            }
    
            var studentList = (
                from i in E.Range(0, n)
                let GE = ge[i]
                let GT = ge[i] + gi[i]
                let APP = appli[i]
                orderby GT descending, GE descending
                select new { id = i, gt = GT, ge = GE, app = APP })
                .ToList();
    
            int[] rank = new int[n];
            for (int i = 0; i < n; i++) {
                var item = studentList[i];
                var lastItem = studentList[i - 1<0?0:i-1];
                if (i!=0 && lastItem.gt == item.gt && lastItem.ge == item.ge)
                    rank[item.id] = rank[lastItem.id];
                else rank[item.id] = i;
                
                for (int j = 0; j < k; j++) {
                    int sel = item.app[j];
                    if (schoolAccept[sel].Count < maxAcc[sel] || rank[schoolAccept[sel].Last()] == rank[item.id]) {
                        schoolAccept[sel].Add(item.id);
                        break;
                    }
                }
            }
    
            for (int i = 0; i < m; i++) {
                schoolAccept[i].Sort();
                for (int j = 0; j < schoolAccept[i].Count; j++) {
                    Console.Write((j == 0 ? "" : " ") + schoolAccept[i][j]);
                }
                Console.WriteLine("");
            }
        }
    
        public static void Main(String[] args) {
            new Program();
        }
    }

    发表于 2016-02-15 23:11:58 回复(0)
    /*
    题意:n个学生可以填k个志愿,m个学校有quota个招生名额,学生优先考虑第一志愿,
    不录取则顺延后面志愿,学校按照ge+gi成绩排名,如果相同,则按ge排名,
    如果一个学校录取了x同学,并且有y同学和x同学两个成绩相同,则即是名额不够也都要录取,
    求最后的录取名单
    
    思路:将学生成绩降序排序,访问完每个人的k个志愿(**分高的先挑学校**)再继续下个人,
    如果第j志愿有名额,直接录取;
    如果第j志愿没有名额了就看看这个学校(第j志愿)有没有招收两项成绩都跟自己相同的,
    有自己就被录取。
    */
    #include <bits/stdc++.h>
    using namespace std;
    const int AX = 4e4 + 6 ;
    int n , m , k ;
    int quota[105] ;
    struct Node {
    	int ge , sum ;
    	int id ;
    	int zy[6] ;
    	bool operator < ( const Node &a )const {
    		if( sum == a.sum ) return ge > a.ge ;
    		return sum > a.sum ;
    	}
    } st_g[AX] ;
    map<int,int>ID;
    vector<Node>st ;
    vector<int>res[105] ;
    int main() {
    	scanf("%d%d%d",&n,&m,&k);
    	for( int i = 0 ; i < m ; i++ ) {
    		scanf("%d",&quota[i]);
    	}
    	int x ;
    	for( int i = 0 ; i < n ; i++ ) {
    		scanf("%d%d",&st_g[i].ge,&x);
    		st_g[i].id = i ;
    		st_g[i].sum = x + st_g[i].ge ;
    		for( int j = 0 ; j < k ; j++ ) {
    			scanf("%d",&x);
    			st_g[i].zy[j] = x ;
    		}
    		st.push_back(st_g[i]);
    	}
    	sort( st.begin() , st.end() );
    	for( int i = 0 ; i < n ; i++ ) {
    		ID[st[i].id] = i ;
    	}
    	for( int i = 0 ; i < n ; i++ ) {
    		for( int j = 0 ; j < k ; j++ ) {
    			int zy = st[i].zy[j] ;
    			if( quota[zy] > 0 ) {
    				quota[zy] -- ;
    				res[zy].push_back(st[i].id);
    				break ;
    			} else {
    				int kk = res[zy].size() - 1 ;
    				if( st[ID[res[zy][kk]]].sum == st[i].sum && st[i].ge == st[ID[res[zy][kk]]].ge ) {
    					quota[zy] -- ;
    					res[zy].push_back(st[i].id) ;
    					break ;
    				}
    			}
    		}
    	}
    	for( int i = 0 ; i < m ; i++ ) {
    		sort( res[i].begin() , res[i].end() );
    		if( !res[i].size() ) printf("\n");
    		else {
    			int len = res[i].size() ;
    			for( int j = 0 ; j < len ; j++ ) {
    				printf("%d",res[i][j]);
    				if( j != len - 1 ) printf(" ");
    			}
    			if( i != m - 1 ) printf("\n");
    		}
    	}
    	return 0 ;
    }
    

    发表于 2020-02-19 18:43:28 回复(3)
    #include <iostream>
    #include <vector>
    #include <algorithm>
    using namespace std;
    
    struct info
    {
        unsigned short id;   //(备注:)采用unsigned short 是因为满足大于40000的要求
        unsigned short Ge;   //如果采用int, info arr[40000] 会造成内存溢出
        float Gsum;
    };
    
    bool cmp(info a, info b)
    {
        if (a.Gsum == b.Gsum)
            return a.Ge > b.Ge;
        else
            return a.Gsum > b.Gsum;
    }
    
    int main()
    {
        int N, M, K, Ge, Gi, vol;
        cin>>N>>M>>K;
        info arr[40000];                     //学生集合;
        vector<int> voluntary[40000];        //学生志愿
        vector<int> admitSchool[100];        //大学集合-招到学生的编号
        int numOfStu[101];                   //大学招生人数
        int curNum[101] = {0};               //当前大学招生的人数
        for (int i=0; i<M; i++)
        {
            cin>>numOfStu[i];
        }
        for (int i=0; i<N; i++)
        {
            cin>>Ge>>Gi;
            arr[i].id = i;
            arr[i].Ge = Ge;
            arr[i].Gsum = float(Ge+Gi)/2.0;
            for (int j=0; j<K; j++)
            {
                cin>>vol;
                voluntary[i].push_back(vol);
            }
        }
        sort(arr, arr+N, cmp);                //完成学生的排名,从高到低
        for (int i=0; i<N; i++)
        {
            for (int j=0; j<K; j++)
            {
                int choose = voluntary[arr[i].id][j];          //当前志愿
                if (numOfStu[choose] > curNum[choose])         //人未招满,直接进入vector
                {
                    admitSchool[choose].push_back(arr[i].id);
                    curNum[choose]++;
                    break;
                }
                else           //招满情况,比较报考学校最后一名学生的成绩和当前学生的成绩
                {
                    int lastId = admitSchool[choose].back(), callID;
                    for (int k=0; k<i; k++)
                    {
                        if (arr[k].id == lastId)
                        {
                            callID = k;
                            break;
                        }
                    }
                    if (arr[callID].Ge==arr[i].Ge && arr[callID].Gsum==arr[i].Gsum)
                    {
                        admitSchool[choose].push_back(arr[i].id);
                        curNum[choose]++;
                        break;
                    }
                }
            }
        }
    
        for (int i=0; i<M; i++)
        {
            sort(admitSchool[i].begin(), admitSchool[i].end());
            bool flag = false;
            for (int j=0; j<curNum[i]; j++)
            {
                if (!flag)
                {
                    cout<<admitSchool[i][j];
                    flag = true;
                }
                else
                    cout<<" "<<admitSchool[i][j];
            }
            cout<<endl;
        }
    
        return 0;
    }
    

    发表于 2018-03-21 17:02:16 回复(1)
    //关键在于如何处理排名完全相同的同学
    //这里采用自定义"<"表示“排名绝对地靠前”,即使如此,排名相同学生仍然凑在一起
    //用set自动排序学生
    //处理排名完全相同的同学,引入lastStu[]记录每个学校上一个录取的同学
    //只要当前同学与他要去的学校的上一个录取同学排名相同,无论如何都录取

    #include <iostream>
    #include <vector>
    #include <set>
    using namespace std;
    
    #define MAX 40009
    int N, M, K, quota[109];
    int E[MAX], I[MAX], goal[MAX][10];
    
    set<int> res[109];int lastStu[109];
    
    typedef struct Stu {
    	int id;
    	Stu() :id(-1) {}
    	Stu(int x) :id(x) {}
    	bool operator <(Stu s)const {//<表示比学生s排名绝对地更靠前
    		if (E[id] + I[id] > E[s.id] + I[s.id])return true;
    		else if (E[id] + I[id] == E[s.id] + I[s.id]) {
    			if (E[id] > E[s.id])return true;
    			else return false;
    		}
    		else return false;
    	}
    }Stu;
    multiset<Stu> gList;
    
    int main()
    {
    	cin >> N >> M >> K; set<int> emp_set;
    	for (int i = 0; i < M; ++i) {
    		cin >> quota[i]; res[i] = emp_set;
    	}
    	for (int i = 0; i < N; ++i) {
    		cin >> E[i] >> I[i];
    		for (int j = 0; j < K; ++j)cin >> goal[i][j];
    		gList.insert(Stu(i));
    	}
    
    	int ID, school;
    	for (auto it = gList.begin(); it != gList.end();++it) {
    		ID = it->id;
    		for (int j = 0; j < K; ++j) {
    			school = goal[ID][j];
    			if (E[ID] + I[ID] == E[lastStu[school]] + I[lastStu[school]] &&
    				E[ID] == E[lastStu[school]] ||
    				res[school].size() < quota[school]) {
    				res[school].insert(ID);
    				lastStu[school] = ID;
    				break;
    			}
    		}
    	}
    
    	for (int i = 0; i < M; ++i) {
    		for (auto it = res[i].begin(); it != res[i].end(); ) {
    			cout << *it;
    			if (++it != res[i].end())cout << " ";
    		}
    		if (i < M - 1)cout << endl;
    	}
    	return 0;
    }
    


    发表于 2021-01-19 00:22:22 回复(0)
    模拟招生,分高的占优势袄~~~
    #include <bits/stdc++.h>
    
    using namespace std;
    
    const int maxn = 4e4 + 5;
    const int maxm = 100 + 5;
    int n, m, k, most[maxm], laste[maxm], lasta[maxm];
    struct node{
        int ge, gi, id;
        int a[10];
        bool operator <( const node &x )const{  //排序规则,总分高在前,若总分相等则Ge高的在前
            if( ge+gi==x.ge+x.gi ) return ge>x.ge;    //不用除以2,也不用开double
            return ge+gi>x.ge+x.gi;
        }
    } stu[maxn];
    vector<int> clg[maxm];
    bool vis[maxn];
    int main()
    {
    //    freopen("in.txt", "r", stdin);
        ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
        cin >> n >> m >> k;
        for( int i=0; i<m; i++ ) cin >> most[i];
        for( int i=0; i<n; i++ ){
            cin >> stu[i].ge >> stu[i].gi;
            stu[i].id = i;
            for( int j=0; j<k; j++ ) cin >> stu[i].a[j];
        }
        sort( stu, stu+n );
        //分高的先选,把所有志愿遍历一遍
        for( int j=0; j<n; j++ ){
            for( int i=0; i<k; i++ ){
                if( vis[stu[j].id] ) continue;  //如果已经被录取则ontinue
                int cid = stu[j].a[i];
                if( clg[cid].size()<most[cid] ){   //编号cid的大学没招满,直接录取
                    clg[cid].push_back(stu[j].id);
                    lasta[cid] = (laste[cid]=stu[j].ge)+stu[j].gi;
                    vis[stu[j].id]=1;
                }else if( lasta[cid]==stu[j].ge+stu[j].gi && laste[cid]==stu[j].ge ){ //如果当前学生和编号为cid大学的最后一名分相同则录取  
                    clg[cid].push_back(stu[j].id);
                    vis[stu[j].id] = 1;
                }
    
            }
        }
        for( int i=0; i<m; i++ ){
            sort(clg[i].begin(), clg[i].end());     //字典序输出
            int siz = clg[i].size();
            if( !siz ) cout << endl;
            else for( int j=0; j<siz; j++ ){
                if( j ) cout << " ";
                cout << clg[i][j];
            }
            cout << endl;
        }
    
        return 0;
    }
    


    编辑于 2020-01-19 14:45:48 回复(0)
    #include <stdio.h>
    #include <iostream>
    #include <vector>
    #include <set>
    #include <algorithm>
    using namespace std;
    const int maxn = 40001;
    const int maxm = 101;
    struct Applicant {
        int Ge, Gi, Rank, id;
        float final_score;
        vector<int> choice;
    };
    int quota[maxm];
    Applicant applicants[maxn];
    
    bool cmp(Applicant a, Applicant b) {
        if(a.final_score != b.final_score) {
            return a.final_score > b.final_score;
        } else {
            return a.Ge > b.Ge;
        }
    }
    set<int> ans[maxm];
    int main() {
        int n, m, k;
        scanf("%d %d %d", &n,&m, &k);
        for(int i=0; i<m; i++) {
            scanf("%d", quota+i);
        }
        for(int i=0; i<n; i++) {
            scanf("%d %d", &applicants[i].Ge, &applicants[i].Gi);
            for(int j=0; j<k; j++) {
                int tmp;
                scanf("%d", &tmp);
                applicants[i].choice.push_back(tmp);
            }
            applicants[i].final_score = (float)(applicants[i].Ge + applicants[i].Gi)/2;
            applicants[i].id = i;
        }
        sort(applicants, applicants+n, cmp);
    
        applicants[0].Rank = 0;
        for(int i=1; i<n; i++) {
            if(applicants[i].final_score == applicants[i-1].final_score && applicants[i].Ge == applicants[i-1].Ge) {
                applicants[i].Rank = applicants[i-1].Rank;
            } else {
                applicants[i].Rank = i;
            }
        }
    
        int prev_rank[maxm];
        fill(prev_rank, prev_rank+maxm, -1);
        for(int i=0; i<n; i++) {
            for(int j=0; j<k; j++) {
                int school_index = applicants[i].choice[j];
                if(quota[school_index] > 0 || applicants[i].Rank == prev_rank[school_index]) {
                    quota[school_index]--;
                    ans[school_index].insert(applicants[i].id);
                    prev_rank[school_index] = applicants[i].Rank;
                    break;
                }
            }
        }
    
        for(int i=0; i<m; i++) {
            if(!ans[i].empty()) {
                set<int>::iterator it = ans[i].begin();
                printf("%d", *it);
                it++;
                for(; it!=ans[i].end(); it++) {
                    printf(" %d", *it);
                }
            }
    
            printf("\n");
        }
    
    }
    

    发表于 2019-09-19 15:28:51 回复(0)
    #include<bits/stdc++.h>
    using namespace std;
    const int N = 4e4 + 10;
    struct Stu {
    	int x, y, id, b[10];
    	void input(int k, int idx) { 
    		scanf("%d%d", &x, &y);
    		id = idx;
    		for (int i = 0;i < k;i++) scanf("%d", &b[i]);
    	}
    	bool operator < (const Stu &o) const {
    		if (x + y != o.x + o.y) return x + y > o.x + o.y;
    		return x > o.x;
    	}
    	bool operator == (const Stu &o) const {
    		return x == o.x && y == o.y;
    	}
    } stu[N], stu2[N];
    int n, m, k, a[N];
    vector<int> vec[N][10], tmp;
    int main() {
    	//freopen("in.txt", "r", stdin);
    	scanf("%d%d%d", &n, &m, &k);
    	for (int i = 0;i < m;i++) {
    		scanf("%d", &a[i]);
    	}
    	for (int i = 0;i < n;i++) {
    		stu[i].input(k, i);
    		stu2[i] = stu[i];
    	}
    	sort(stu, stu + n);
    	for (int i = 0;i < n;i++) {
    		int idx = stu[i].id;
    		for (int j = 0;j < k;j++) {
    			int sc = stu[i].b[j];
    			if (a[sc] > 0) {
    				a[sc]--, vec[sc][j].push_back(idx);
    				break;
    			} else if (vec[sc][j].size() && stu2[vec[sc][j].back()] == stu[i]) {
    				vec[sc][j].push_back(idx);
    				break;
    			}
    		}
    	}
    	for (int i = 0;i < m;i++) {
    		tmp.resize(0);
    		for (int j = 0;j < k;j++) {
    			for (int x : vec[i][j]) tmp.push_back(x);
    		}
    		sort(tmp.begin(), tmp.end());
    		for (int j = 0;j < tmp.size();j++) {
    			printf("%d", tmp[j]);
    			if (j != tmp.size() - 1) printf(" ");
    		}
    		printf("\n");
    	}
    	return 0;
    }
    
    
    为什么我最后一个点错了,有没有大佬帮忙看看那里出了问题
    发表于 2023-03-04 17:35:16 回复(0)


    更多PAT题解--acking=you.github.io

    题目

    OJ平台

    题目翻译

    实际上就和我们高考录取的过程是一样的。
    题目是给出了N个考生的两种成绩(初试和复试)。
    每个考生填满K个学校志愿。
    然后通过成绩的高低(初试和复试的总和)决定录取的先后顺序。
    每个学校有相应的名额限制,如果出现两个初试和复试分数都完全一样的人,则名额不存在限制。
    最后要我们输出每个学校的录取名单(以0~N-1代号表示学生)。

    我的解题思路

    • 如何模拟这整个录取过程呢?
    1. 把输入的数据先存下来。
    2. 将学生的成绩(总和成绩、初试成绩)和学生编号进行映射。
    3. 通过映射好的数组自定义排序,把总和成绩好的放前面,如果总和成绩相同,则比较初试成绩。
    4. 在前面的人,他拥有优先选择权,通过他这个编号找到他对应的志愿表,并从头到尾录取。(录取通过一个 AdmissionList[i] 数组存下编号为 i 的学校的录取情况)
    5. 通过 AdmissionList[i] 数组存下录取情况的过程中,需要判断这个学校是否已经录满了,如果录取满了,则和它的最低分进行比较,如果和它完全相同则继续录取(不可能比它大,因为本就已经排好序进行录取的)
    6. 最后再通过 AdmissionList 打印结果即可。

    代码解读

    基本的变量

    基本变量

    int *schoolN;                               //存储每个学校的限额
    int **studentN;                             //存储每个学生的分数和志愿
    vector<tuple<int, int, int>> students_sort; //这个只是用来排序的工具
    vector<tuple<int, int, int>> *AdmissionList;//存储每个学校的录取名单
    /*其实可以把tuple用自定义的数据结构代替,只是C++11标准自带我就直接拿这个过来用了*/

    tuple的使用方法

    make_tuple()         //可以用于创建tuple对象
    get<0~N>(tuple<>)    //0~N表示要访问的下标

    存储输入的数据

    void Input() {//先把数据存起来再说
        ios::sync_with_stdio(false);
        cin >> N >> M >> K;
        schoolN = new int[M];
        studentN = new int *[N];
        students_sort.resize(N);
        AdmissionList = new vector<tuple<int, int, int>>[M];
        for (int i = 0; i < M; i++) {
            int x;
            cin >> x;
            schoolN[i] = x;
        }
        for (int i = 0; i < N; i++) {
            int n = 2 + K;
            int *t = new int[n];
            for (int j = 0; j < n; j++) {
                int x;
                cin >> x;
                t[j] = x;
            }
            studentN[i] = t;
        }
    }

    自定义排序模块

    对学生通过分数进行排序,决定志愿录取的先后顺序

    bool cmp1(tuple<int, int, int> &a, tuple<int, int, int> &b) {//如果总成绩不相同,则成绩高的放前面,否则再看初试成绩
        return (get<0>(a) > get<0>(b)) || (get<0>(a) == get<0>(b) && get<1>(a) > get<1>(b));
    }

    用于对答案编号按照从小到大输出

    bool cmp2(tuple<int, int, int> &a, tuple<int, int, int> &b) {
        return get<2>(a) < get<2>(b);
    }

    用于判断两个学生是否完全相同和得到学生编号

    inline bool IsEqual(tuple<int, int, int> &a, tuple<int, int, int> &b) {
        return get<0>(a) == get<0>(b) && get<1>(a) == get<1>(b);
    }
    
    inline int get_val(tuple<int, int, int> &a) {
        return get<2>(a);
    }

    核心模块--答案的更新

    void solve() {
        for (int i = 0; i < N; i++) { //先根据成绩把学生排个序(相当于处理录取时候的顺序)
            for (int j = 2; j < K + 2; j++) {
                int sumP = studentN[i][0] + studentN[i][1];
                int G = studentN[i][0];
                students_sort[i] = make_tuple(sumP, G, i);
            }
        }
        sort(students_sort.begin(), students_sort.end(), cmp1); //排好序后,决定了录取的优先顺序
    
        //以下为模拟录取过程
        for (int i = 0; i < N; i++) {
            int node = get<2>(students_sort[i]);
            //遍历这个学生的各个志愿
            for (int j = 2; j < K + 2; j++) {
                auto sz = AdmissionList[studentN[node][j]].size();
                if (sz < schoolN[studentN[node][j]]) {
                    AdmissionList[studentN[node][j]].push_back(students_sort[i]);
                    break;
                } else {
                    auto &t = AdmissionList[studentN[node][j]].back();
                    if (IsEqual(students_sort[i], t)) {//如果完全相同则破例录取
                        AdmissionList[studentN[node][j]].push_back(students_sort[i]);
                        break;
                    }
                }
            }
        }
    }

    最后--打印答案

    void print() {
        for (int i = 0; i < M; i++) {
            auto sz = AdmissionList[i].size();
            sort(AdmissionList[i].begin(), AdmissionList[i].end(), cmp2);//打印前先编号从小到大排序
            for (int j = 0; j < sz; j++) {
                if (j != sz - 1) {
                    cout << get_val(AdmissionList[i][j]) << ' ';
                } else cout << get_val(AdmissionList[i][j]);
            }
            if (i != M - 1)
                cout << endl;
        }
    }

    整合代码提交

    效率yyds

    #include<bits/stdc++.h>
    
    using namespace std;
    int N, M, K;
    int *schoolN;                               //存储每个学校的限额
    int **studentN;                             //存储每个学生的分数和志愿
    vector<tuple<int, int, int>> students_sort; //这个只是用来排序的工具
    vector<tuple<int, int, int>> *AdmissionList;//存储每个学校的录取名单
    //@输入和更新数据
    void Input() {//先把数据存起来再说
        ios::sync_with_stdio(false);
        cin >> N >> M >> K;
        schoolN = new int[M];
        studentN = new int *[N];
        students_sort.resize(N);
        AdmissionList = new vector<tuple<int, int, int>>[M];
        for (int i = 0; i < M; i++) {
            int x;
            cin >> x;
            schoolN[i] = x;
        }
        for (int i = 0; i < N; i++) {
            int n = 2 + K;
            int *t = new int[n];
            for (int j = 0; j < n; j++) {
                int x;
                cin >> x;
                t[j] = x;
            }
            studentN[i] = t;
        }
    }
    
    //@更新答案
    bool cmp1(tuple<int, int, int> &a, tuple<int, int, int> &b) {
        return (get<0>(a) > get<0>(b)) || (get<0>(a) == get<0>(b) && get<1>(a) > get<1>(b));
    }
    inline bool IsEqual(tuple<int, int, int> &a, tuple<int, int, int> &b) {
        return get<0>(a) == get<0>(b) && get<1>(a) == get<1>(b);
    }
    inline int get_val(tuple<int, int, int> &a) {
        return get<2>(a);
    }
    void solve() {
        for (int i = 0; i < N; i++) { //先根据成绩把学生排个序(相当于处理录取时候的顺序)
            for (int j = 2; j < K + 2; j++) {
                int sumP = studentN[i][0] + studentN[i][1];
                int G = studentN[i][0];
                students_sort[i] = make_tuple(sumP, G, i);
            }
        }
        sort(students_sort.begin(), students_sort.end(), cmp1); //排好序后,就根据这个顺序给学生进行录取
    
        //以下为模拟录取过程
        for (int i = 0; i < N; i++) {
            int node = get<2>(students_sort[i]);
            for (int j = 2; j < K + 2; j++) {
                auto sz = AdmissionList[studentN[node][j]].size();
                if (sz < schoolN[studentN[node][j]]) {
                    AdmissionList[studentN[node][j]].push_back(students_sort[i]);
                    break;
                } else {
                    auto &t = AdmissionList[studentN[node][j]].back();
                    if (IsEqual(students_sort[i], t)) {
                        AdmissionList[studentN[node][j]].push_back(students_sort[i]);
                        break;
                    }
                }
            }
        }
    }
    
    
    //@打印答案
    bool cmp2(tuple<int, int, int> &a, tuple<int, int, int> &b) {
        return get<2>(a) < get<2>(b);
    }
    void print() {
        for (int i = 0; i < M; i++) {
            auto sz = AdmissionList[i].size();
            sort(AdmissionList[i].begin(), AdmissionList[i].end(), cmp2);
            for (int j = 0; j < sz; j++) {
                if (j != sz - 1) {
                    cout << get_val(AdmissionList[i][j]) << ' ';
                } else cout << get_val(AdmissionList[i][j]);
            }
            if (i != M - 1)
                cout << endl;
        }
    }
    
    int main() {
        Input();
        solve();
        print();
        return 0;
    }

    题外话

    • 讲实话,这个题目感觉就是在写业务代码,实现一个实际功能的。我是比较喜欢这类题型的,感觉这种算法题就比较实用!
    发表于 2021-09-28 18:41:17 回复(0)
    第一次想复杂了,码出来答案也对,但是超时了4个,他怎么录取感觉题干也没怎么说清楚,后来意识到就是平行志愿,从分高往分低录取就行了
    #include <iostream>
    #include <vector>
    #include <algorithm>
    using namespace std;
    int stu_num,sch_num,cho_num;
    vector<int> temp1;
    vector<int> temp2;
    vector<int> sch;
    vector<vector<int>> choice;
    vector<vector<int>> choice1;
    vector<vector<int>> sch_list;
    bool cmp(vector<int> i,vector<int> j){
        
        if (i[1]+i[2]!=j[1]+j[2]) {
            return i[1]+i[2]>j[1]+j[2];
        }else
            return i[1]>j[1];
    }
    int main(int argc, const char * argv[]) {
        int t;
        cin>>stu_num>>sch_num>>cho_num;
        for (int i=0; i<sch_num; i++) {
            cin>>t;
            sch.push_back(t);
            sch_list.push_back(temp1);
        }
        for (int i=0; i<stu_num; i++) {
            temp1.push_back(i);
            for (int j=0; j<cho_num+2; j++) {
                cin>>t;
                temp1.push_back(t);
                temp2.push_back(t);
            }
            choice.push_back(temp1);
            choice1.push_back(temp2);
            temp1.clear();
            temp2.clear();
        }
        sort(choice.begin(), choice.end(), cmp);
        for (int i=0; i<stu_num; i++) {
            for (int j=0; j<cho_num; j++) {
                if (sch[choice[i][j+3]]>0) {
                    sch_list[choice[i][j+3]].push_back(choice[i][0]);
                    sch[choice[i][j+3]]--;
                    break;
                }else if(choice1[sch_list[choice[i][j+3]].back()][1]==choice1[choice[i][0]][1]&&choice1[sch_list[choice[i][j+3]].back()][0]==choice1[choice[i][0]][0]){
                    sch_list[choice[i][j+3]].push_back(choice[i][0]);
                    sch[choice[i][j+3]]--;
                    break;
                }
            }
        }
        for (int i=0; i<sch_num; i++) {
            if (sch_list[i].size()!=0) {
                sort(sch_list[i].begin(), sch_list[i].end());
                auto it=sch_list[i].begin();
                while (it!=sch_list[i].end()) {
                cout<<*it;
                it++;
                if (it!=sch_list[i].end()) {
                    cout<<" ";
                }else
                    cout<<endl;
                }
            }else
                cout<<endl;
        }
        return 0;
    }



    编辑于 2021-02-20 00:25:02 回复(0)
    #include <iostream>
    #include <algorithm>
    #include <vector>
    using namespace std;
    const int STUDENT_SIZE = 4e4;
    const int SCHOOL_SIZE = 100;
    
    struct student
    {
        float exam_grade, final_grade;
        int ID;
        vector<int> choice;
    } s[STUDENT_SIZE];
    
    int _size[SCHOOL_SIZE];
    vector<student> admission[SCHOOL_SIZE];
    
    bool cmp1(student a, student b)
    {
        if (a.final_grade == b.final_grade)
            return a.exam_grade > b.exam_grade;
        return a.final_grade > b.final_grade;
    }
    
    bool cmp2(student a, student b)
    {
        return a.ID < b.ID;
    }
    
    int main()
    {
        int n, m, k;
        cin >> n >> m >> k;
        for (int i = 0; i < m; i++)
            cin >> _size[i];
        for (int i = 0; i < n; i++)
        {
            float u, v;
            cin >> u >> v;
            s[i].exam_grade = u;
            s[i].final_grade = (u + v) / 2;
            s[i].ID = i;
            for (int j = 0; j < k; j++)
            {
                int w;
                cin >> w;
                s[i].choice.push_back(w);
            }
        }
        sort(s, s + n, cmp1);
        for (int i = 0; i < n; i++)
        {
            for (int j = 0; j < s[i].choice.size(); j++)
            {
                int u = s[i].choice[j];
                if (admission[u].size() < _size[u])
                {
                    admission[u].push_back(s[i]);
                    break;
                }
                else
                {
                    if (admission[u].back().final_grade == s[i].final_grade && admission[u].back().exam_grade == s[i].exam_grade)
                    {
                        admission[u].push_back(s[i]);
                        break;
                    }
                }
            }
        }
        for (int i = 0; i < m; i++)
        {
            sort(admission[i].begin(), admission[i].end(), cmp2);
            for (auto t : admission[i])
                cout << t.ID << " ";
            cout << endl;
        }
        return 0;
    }

    发表于 2020-06-03 12:11:54 回复(0)
    #include<bits/stdc++.h>
    #define N 40011
    #define K 111
    using namespace std;
    struct node{
    	int ge,gi,total,rank,num;
    	vector<int> applicant;
    }data[N];
    bool cmp(node n1,node n2){
    	return n1.total!=n2.total?n1.total>n2.total:n1.ge>n2.ge;
    }
    int main(){
    	int n,k,i,j,m;
    	int q[K]={0};
    	set<int> admit[K],admitRank[K];
    	cin>>n>>m>>k;
    	for(i=0;i<=m-1;i++)cin>>q[i];
    	for(i=0;i<=n-1;i++){
    		data[i].num=i;
    		cin>>data[i].ge>>data[i].gi;
    		data[i].total=data[i].ge+data[i].gi;
    		data[i].applicant.resize(k);
    		for(j=0;j<=k-1;j++)
    			cin>>data[i].applicant[j];
    		
    	}
    	sort(data,data+n,cmp);
    	data[0].rank=0;
    	for(i=1;i<=n-1;i++){
    		if(data[i].total==data[i-1].total&&data[i].ge==data[i-1].ge)
    			data[i].rank=data[i-1].rank;
    		else 
    			data[i].rank=i;
    	}
    	for(i=0;i<=n-1;i++){
    		for(auto it:data[i].applicant)
    			if(q[it]>0){
    				admit[it].insert(data[i].num);
    				admitRank[it].insert(data[i].rank);
    				q[it]--;
    				break;
    			}
    			else if(admitRank[it].count(data[i].rank)){
    				admit[it].insert(data[i].num);
    				break;
    			}		
    	}
    	for(i=0;i<=m-1;i++,cout<<endl){
    		if(admit[i].empty())continue;
    		auto it=admit[i].begin();
    		cout<<*it;
    		for(it++;it!=admit[i].end();it++)
    			cout<<' '<<*it;
    	}	
    	return 0;
    }
    C++的,主要利用STL
    编辑于 2020-03-01 20:38:00 回复(0)
    #include<iostream>
    (720)#include<vector>
    #include<algorithm>
    using namespace std;
    const int maxM = 101;
    const int maxN = 40001;
    struct applicant {
    	int number;
    	int GE;
    	int GI;
    	vector<int>priority;//选择学校的先后顺序
    	applicant(int number, int ge, int gi, vector<int>p) :number(number), GE(ge), GI(gi), priority(p) {}
    };
    bool cmp(applicant a, applicant b) {
    	if (a.GE + a.GI > b.GE + b.GI) { return true; }
    	else if (a.GE + a.GI < b.GE + b.GI) { return false; }
    	else { return a.GE > b.GE; }
    }
    int main() {
    	//freopen("C:\\Users\\47\\Desktop\\1.txt", "r", stdin);
    	int n, m, k;
    	cin >> n >> m >> k;
    	vector<applicant>applicants;
    	vector<applicant>tmp;
    	vector<int>school;//每个学校的预留人数
    	vector<int>school_app[maxM];//每个学校的最终选定人
    	vector<int>rank;//每个学生排序后的rank排名
    	for (int i = 0; i < m; i++) {
    		int quota;
    		cin >> quota;
    		school.push_back(quota);
    	}
    	for (int i = 0; i < n; i++) {
    		int GE, GI, p;
    		cin >> GE >> GI;
    		vector<int>tmp;
    		for (int i = 0; i < k; i++) {
    			cin >> p;
    			tmp.push_back(p);
    		}
    		applicants.push_back(applicant(i, GE, GI, tmp));
    	}
    	tmp = applicants;
    	sort(applicants.begin(), applicants.end(), cmp);
    	for (int i = 0; i < applicants.size(); i++) {
    		applicant one = applicants[i];
    		for (int j = 0; j < one.priority.size(); j++) {
    			int sc = one.priority[j];
    			if (school[sc]) {
    				school_app[sc].push_back(one.number);
    				school[sc]--;
    				break;
    			}
    			else {
    				int pre = school_app[sc][school_app[sc].size() - 1];//这里的pre是编号,并不一定对应applicants中的下标19
    				if (tmp[pre].GE == one.GE && tmp[pre].GI == one.GI) {
    					school_app[sc].push_back(one.number);
    					break;
    				}
    			}
    		}
    	}
    	for (int i = 0; i < m; i++) {
    		sort(school_app[i].begin(),school_app[i].end());
    		for (int j = 0; j < school_app[i].size(); j++) {
    			if (j) printf(" ");
    			printf("%d", school_app[i][j]);
    		}
    		printf("\n");
    	}
    }

    发表于 2020-02-28 12:37:26 回复(0)
    //牛客过不了最后一个点,pat全过
    #define _CRT_SECURE_NO_WARNINGS
    (842)#include <iostream>
    #include <algorithm>
    (831)#include <cmath>
    #include <string>
    (765)#include <vector>
    #include <set>
    (855)#include <queue>
    #include <map>
    (747)#include <iomanip>
    #include <sstream>
    using namespace std;
    
    //1080 Graduate Admission
    //同分同名
    //编号均为0开始。
    
    class stu {
    public:
    	int id, ge, gi, rank;
    	float fg;//final grade
    	vector<int> choices;
    	int result;
    	stu() :ge(0), gi(0), fg(0), result(-2){}
    };
    
    class col {
    public:
    	int quota;
    	vector<int> adm;
    };
    col colleges[105] = {};
    stu stus[40005];
    
    bool cmp(stu &a, stu&b) {
    	if (a.fg != b.fg) return a.fg > b.fg;
    	else if (a.ge != b.ge) return a.ge > b.ge;
    	else return a.id<b.id; //按号码升序
    }
    
    int n, m, k;
    int len;
    
    int main() {
    	cin >> n >> m >> k;
    
    	//数据录入
    	int quo;
    	for (int i = 0; i < m; ++i) {
    		scanf("%d", &quo);
    		colleges[i].quota = quo;
    	}
    
    	//学生申请
    	int e_, i_, c;
    	for (int i = 0; i < n; ++i) {
    		scanf("%d%d", &e_, &i_);
    		stus[i].id = i;
    		stus[i].ge = e_;
    		stus[i].gi = i_;
    		stus[i].fg = float(e_ + i_) / 2;
    		for (int j = 0; j < k; ++j) {
    			scanf("%d", &c);
    			stus[i].choices.push_back(c);
    		}
    	}
    
    	//排序
    	sort(stus, stus + n, cmp);
    
    	//排名更新
    	stus[0].rank = 0;//rank从第0名开始
    	for (int i = 1; i < n; ++i) {
    		if (stus[i].gi == stus[i - 1].gi && stus[i].ge == stus[i - 1].ge)
    			stus[i].rank = stus[i - 1].rank;
    		else
    			stus[i].rank = i;
    	}
    
    	//模拟投递
    
    	//先对0号选手做一次
    	for (int j = 0; j < k; ++j) {
    		int cur_c = stus[0].choices[j];
    		if (colleges[cur_c].quota > 0) {
    			colleges[cur_c].adm.push_back(stus[0].id);
    			colleges[cur_c].quota--;
    			stus[0].result = cur_c;
    		}
    		break; //录取后不再看后面志愿
    	}
    	//然后是后面选手
    	for (int i = 1; i < n; ++i) {
    		for (int j = 0; j < k; ++j) {
    			int cur_c = stus[i].choices[j];
    			if (colleges[cur_c].quota > 0) {
    				//你被录取了
    				colleges[cur_c].adm.push_back(stus[i].id);
    				colleges[cur_c].quota--;
    				stus[i].result = cur_c;
    				break;//录取后不再看后面志愿
    			}
    			else if (stus[i].rank == stus[i - 1].rank && cur_c == stus[i - 1].result) {
    				//同分挤进去,你被录取了
    				colleges[cur_c].adm.push_back(stus[i].id);
    				colleges[cur_c].quota--;
    				stus[i].result = cur_c;
    				break;
    			}
    		}
    	}
    
    	//输出结果
    	for (int i = 0; i < m; ++i) {
    		len = colleges[i].adm.size();
    		if (len == 0) {
    			cout << endl; 
    			continue;
    		}
    		//若不为0还需要内部排序一次
    		sort(colleges[i].adm.begin(), colleges[i].adm.end(), less<int>());
    		cout << colleges[i].adm[0];
    		for (int j =1; j < len; ++j) {
    			cout << " " << colleges[i].adm[j];
    		}
    		cout << endl;
    	}
    	return 0;
    }

    发表于 2020-02-24 11:14:23 回复(0)
    a = list(map(int,input().split()))
    b = list(map(int,input().split()))
    c = [list(map(int,input().split())) + [i]for i in range(a[0])]
    m,p = [[] for i in b],[]
    
    for i in sorted(c,key = lambda x:[sum(x[:2]),x[0]])[::-1]:
        for j in i[2:-1]:
            if b[j] > 0 or [sum(i[:2]),i[0],j] == p:
                m[j].append(i[-1])
                b[j],p = b[j] - 1,[sum(i[:2]),i[0],j]
                break
    print("\n".join([' '.join(map(str,sorted(i))) for i in m]))
    pta上用例4可能超时

    编辑于 2020-07-15 18:37:29 回复(0)
    不知道为什么,最后一个测试点重载运算符会报段错误,改成cmp后就过了
    #include <iostream>
    #include <algorithm>
    #include <cstdio>
    using namespace std;
    
    struct _rank{
        int id;
        int g;
        int ge;
        _rank(int _id=0,int _g=0,int _ge=0){
            id =_id;
            g =_g;
            ge =_ge;
        }
    };
    bool cmp(_rank &a,_rank &b){
        if(a.g!=b.g) return a.g>b.g;
        else return a.ge>b.ge;
    }
    bool cmp2(int a,int b){
        return a<b;
    }
    int main()
    {
        int n,m,k;
        scanf("%d %d %d",&n,&m,&k);
        int quota[m];
        for(int i=0;i<m;i++){
            int t;
            scanf("%d",&t);
            quota[i]=t;
        }
        _rank rk[n+1];
        for(int i=0;i<=n;i++)
            rk[i] =_rank(0,0,0);
        int target[n][k];
        for(int i=0;i<n;i++)
            for(int j=0;j<k;j++)
            target[i][j] =0;
        for(int i=0;i<n;i++){
            int g1,g2;
            scanf("%d %d",&g1,&g2);
            rk[i].ge=g1;
            rk[i].g=g1+g2;
            rk[i].id=i;
            for(int j=0;j<k;j++){
                int a;
                scanf("%d",&a);
                target[i][j]=a;
            }
        }
        sort(rk,rk+n,cmp);
        int r[n];
        for(int i=0;i<n;i++)
            r[i] =0;
        int s=0;
        r[rk[0].id] =0;
        for(int i=1;i<n;i++){
            if(!(rk[i].g==rk[i-1].g&&rk[i].ge==rk[i-1].ge))
                s++;
            r[rk[i].id] =s;
        }
        int adm[m][n+1];
        for(int i=0;i<m;i++)
            for(int j=0;j<=n;j++)
            adm[i][j] =-1;
        int len[m],r2[m];
        for(int i=0;i<m;i++){
            len[i] =0;
            r2[i] =-1;
        }
        for(int i=0;i<n;i++){
            int t=rk[i].id;
            for(int j=0;j<k;j++){
                int a=target[t][j];
                if(len[a]<quota[a]||(r2[a]!=-1&&r2[a]==r[t])){
                    adm[a][len[a]] =t;
                    len[a]++;
                    if(len[a]==quota[a]) r2[a] =r[t];
                    break;
                }
            }
        }
        for(int i=0;i<m;i++){
            int t =len[i];
            if(t>0){
                sort(&adm[i][0],&adm[i][0]+t,cmp2);
                printf("%d",adm[i][0]);
                for(int j=1;adm[i][j]!=-1;j++){
                    int a=adm[i][j];
                    printf(" %d",a);
                }
            }
            printf("\n");
        }
        return 0;
    }


    发表于 2020-01-27 21:42:13 回复(0)
    注意一个坑,题目公式里写得/2,但不能用int,得写/2.0,不然会漏半分。
    还有一个是abs的问题,不知道标准库里搞什么乱七八糟的东西,建议用fabs。
    其它的按题意写就行。

    #include <iostream>
    #include <vector>
    #include <functional>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    
    struct Grade{
        int id;
        int ge;
        int gi;
        Grade(int id, int ge, int gi): id(id), ge(ge), gi(gi){}
    };
    
    bool operator >(const Grade& lhs, const Grade& rhs){
        double ls = (lhs.ge + lhs.gi) / 2.0;
        double rs = (rhs.ge + rhs.gi) / 2.0;
        if(std::fabs(ls - rs) < 1e-5){
            return lhs.ge > rhs.ge;
        }
        return ls > rs;
    }
    
    bool operator ==(const Grade& lhs, const Grade& rhs){
        double ls = (lhs.ge + lhs.gi) / 2.0;
        double rs = (rhs.ge + rhs.gi) / 2.0;
        return (std::fabs(ls - rs) < 1e-5 && lhs.ge == rhs.ge);
    }
    
    int main(){
        int N, M, K;
        cin >> N >> M >> K;
        vector<int> quotas(M);
        for(int i = 0; i < M; i++){
            cin >> quotas[i];
        }
        vector<vector<int>> apts(N);
        vector<Grade> grades;
        for(int i = 0; i < N; i++){
            int ge, gi;
            cin >> ge >> gi;
            for(int j = 0; j < K; j++){
                int school;
                cin >> school;
                apts[i].push_back(school);
            }
            grades.emplace_back(i, ge, gi);
        }
        sort(begin(grades), end(grades), greater<Grade>{});
        vector<vector<Grade>> accepted(M);
        for(auto& g : grades){
            for(auto sc : apts[g.id]){
                if(
                    (int)accepted[sc].size() < quotas[sc] ||
                    (!accepted[sc].empty() && accepted[sc].back() == g)
                ){
                    accepted[sc].push_back(g);
                    break;
                }
            }
        }
        vector<int> ids;
        for(auto& gs : accepted){
            ids.clear();
            for(auto& g : gs){
                ids.push_back(g.id);
            }
            sort(begin(ids), end(ids));
            for(int i = 0; i < (int)ids.size(); i++){
                if(i) cout << " ";
                cout << ids[i];
            }
            cout << endl;
        }
    }
    


    发表于 2019-08-24 23:49:11 回复(0)
    #include<iostream>
    #include<stdio.h>
    #include<algorithm>
    #include<vector>
    #define sum(i) i.s1 + i.s2
    using namespace std;
    struct School {
    	int minRank;	//录取的最低排名
    	int stuNum;		//计划收取的学生数
    	vector<int> stu;	//录取的学生
    };
    struct Student{
    	int index;		//学生编号
    	int s1, s2;		//科目一和科目二分数
    	int rank;		//排名
    	int choose[6];	//志愿
    };
    int stuNum, schNum, choNum;
    bool func(Student &a, Student &b){
    	if (sum(a) != sum(b)) return sum(a) > sum(b);
    	return a.s1 > b.s1;
    }
    School school[101];
    Student student[40001];
    int main(){
    	scanf("%d%d%d", &stuNum, &schNum, &choNum);
    	for (int i = 0; i < schNum; i++) scanf("%d", &school[i].stuNum);
    	for (int i = 0; i < stuNum; i++){
    		student[i].index = i;
    		scanf("%d%d", &student[i].s1, &student[i].s2);
    		for (int j = 0; j < choNum; j++) scanf("%d", &student[i].choose[j]);
    	}
    	sort(student, student + stuNum, func);
    	student[0].rank = 1;
    	//为学生成绩排名
    	for (int i = 1; i < stuNum; i++) {
    		if (sum(student[i]) == sum(student[i - 1]) && student[i].s1 == student[i - 1].s1) {
    			student[i].rank = student[i - 1].rank;
    		}
    		else{
    			student[i].rank = student[i - 1].rank + 1;
    		}
    		//cout << "------->" <<i << "   " << student[i].rank << endl;
    	}
    	//学生选择学校
    	for (int i = 0; i < stuNum; i++){
    		for (int j = 0; j < choNum; j++) {
    			int want = student[i].choose[j];
    			if (school[want].stuNum > 0 || school[want].minRank == student[i].rank){
    				school[want].stu.push_back(student[i].index);
    				school[want].stuNum--;
    				school[want].minRank = student[i].rank;
    				break;
    			}
    		}
    	}
    	//输出录取状况
    	for (int i = 0; i < schNum; i++){
    		sort(school[i].stu.begin(), school[i].stu.end());
    		if (school[i].stu.empty()) {
    			cout << endl;
    			continue;
    		}
    		cout << school[i].stu[0];
    		for (int j = 1; j < school[i].stu.size(); j++) cout <<" "<<school[i].stu[j] ;
    		cout << endl;
    	}
    }
    
    发表于 2019-07-13 22:14:08 回复(0)
    最后一个样例通不过? Why??????
    #include<iostream>
    #include<vector>
    #include<algorithm>

    using namespace std;

    struct Grade {
        unsigned short GE;
        unsigned short GT;
        unsigned short index;
    };
    int N, M, K;
    vector<unsigned short> quota;
    vector<vector<unsigned short> > prefer_list(40001);
    vector<Grade> Grade_list(40001);
    vector<vector<unsigned short> > Admission_list(101);

    bool cmp(Grade a,Grade b) {
        if (a.GE + a.GT != b.GE + b.GT)
            return a.GE + a.GT > b.GE + b.GT;
        else
            return a.GE > b.GE;
    }

    int main() {
        cin >> N >> M >> K;
        for (int i = 0; i < M; i++) {
            unsigned short tem;    cin >> tem;
            quota.push_back(tem);
        }
        for (int i = 0; i < N; i++) {
            unsigned short GE, GT;    cin >> GE >> GT;
            Grade tem;    tem.GE = GE;    tem.GT = GT;    tem.index = i;
            Grade_list.push_back(tem);
            vector<unsigned short> v;
            for (int j = 0; j < K; j++) {
                unsigned short x;    cin >> x;
                v.push_back(x);
            }
            prefer_list[i] = v;
        }
        sort(Grade_list.begin(), Grade_list.end(), cmp);
        int preGrade = Grade_list[0].GE + Grade_list[0].GT;
        for (int i = 0; i < N; i++) {
            unsigned short index = Grade_list[i].index;
            for (int j = 0; j < K; j++) {
                int School_ID = prefer_list[index][j];
                int cur_Admission_num = Admission_list[School_ID].size();
                if (cur_Admission_num < quota[School_ID]) {
                    Admission_list[School_ID].push_back(index);
                    break;
                }
                else {
                    int last_Stu_ID = Admission_list[School_ID][cur_Admission_num - 1];
                    if (Grade_list[index].GE == Grade_list[last_Stu_ID].GE&&Grade_list[index].GT == Grade_list[last_Stu_ID].GT) {
                        Admission_list[School_ID].push_back(index);
                        break;
                    }
                }
            }
        }

        for (int i = 0; i < M; i++) {
            sort(Admission_list[i].begin(), Admission_list[i].end());
            if (i != M - 1) {
                if (Admission_list[i].size() == 0) {
                    cout << endl;
                    continue;
                }
                for (int j = 0; j < Admission_list[i].size(); j++) {
                    if (j != Admission_list[i].size() - 1)
                        cout << Admission_list[i][j] << " ";
                    else
                        cout << Admission_list[i][j] << endl;
                }
            }
            else {
                for (int j = 0; j < Admission_list[i].size(); j++) {
                    if (j != Admission_list[i].size() - 1)
                        cout << Admission_list[i][j] << " ";
                    else
                        cout << Admission_list[i][j];
                }
            }
        }
        system("pause");
        return 0;
    }

    发表于 2019-06-03 11:25:49 回复(2)

    没什么难度,直接排序就行

    #include <algorithm>
    #include <cstdio>
    #include <iostream>
    #include <vector>
    using namespace std;
    
    struct student {
      int id, ge, gi;
      int choices[5];
      friend bool operator==(const student& s1, student& s2) {
        return s1.ge == s2.ge && s1.gi == s2.gi;
      }
    } apps[40000 + 5];
    int order[40000 + 5];  // use id to find sorted order
    int schools[105];
    int n, m, k;
    
    bool cmp(student s1, student s2) {
      int f1 = s1.ge + s1.gi, f2 = s2.ge + s2.gi;
      if (f1 != f2) {
        return f1 > f2;
      }
      return s1.ge > s2.ge;
    }
    
    int main() {
      scanf("%d%d%d", &n, &m, &k);
      vector<int> quotas[m];
      for (int i = 0; i < m; i++) {
        scanf("%d", &schools[i]);
      }
      for (int i = 0; i < n; i++) {
        apps[i].id = i;
        scanf("%d%d", &apps[i].ge, &apps[i].gi);
        for (int j = 0; j < k; j++) {
          scanf("%d", &apps[i].choices[j]);
        }
      }
      sort(apps, apps + n, cmp);
      for (int i = 0; i < n; i++) {
        order[apps[i].id] = i;
      }
      for (int i = 0; i < n; i++) {
        for (int j = 0; j < k; j++) {
          int choice = apps[i].choices[j];
          if (schools[choice] != 0) {
            quotas[choice].push_back(apps[i].id);
            schools[choice]--;
            break;
          } else {
            // same app
            student s = apps[order[quotas[choice][quotas[choice].size() - 1]]];
            if (apps[i] == s) {
              quotas[choice].push_back(apps[i].id);
              break;
            }
          }
        }
      }
      for (int i = 0; i < m; i++) {
        if (quotas[i].size() == 0) {
          printf("\n");
        } else {
          sort(quotas[i].begin(), quotas[i].end());
          for (int j = 0; j < quotas[i].size(); j++) {
            if (j != 0) printf(" ");
            printf("%d", quotas[i][j]);
          }
          if (i != m - 1) printf("\n");
        }
      }
      return 0;
    }
    发表于 2019-04-23 13:14:51 回复(0)
    ranklst = []
    n,m,k = map(int,input().split())
    #boolst = [True for i in range(n)]
    out = [[] for i in range(m)]
    dinge = list(map(int,input().split()))
    lst = []
    for i in range(n):
        te = list(map(int,input().split()))
        te.append(i)
        lst.append(te)
    lst.sort(key=lambda x:(-x[0]-x[1],-x[0]))
    ran,ran1 = 0,1
    for i in range(0,len(lst)-1):
        lst[i].append(ran)
        for j in range(i+1,len(lst)):
            if lst[i][0]==lst[j][0] and (lst[i][0]+lst[i][1])==(lst[j][0]+lst[j][1]):
                ran1+=1
                break
            else:
                ran+=ran1
                ranklst.append(i+1)
                ran1=1
                break
    lst[len(lst)-1].append(ran)
    ranklst.append(n)
    ranklst = [0]+ranklst
    backup = list(lst)
    #如果是学校挑人的话:
    #for i in range(2,2+k):
    #     #同一排名的输入
    # for j in range(0,len(ranklst)-1):
    #     for l in range(ranklst[j],ranklst[j+1]):
    #         if boolst[l]:
    #             te = set([])
    #             if dinge[lst[l][i]]>0 or (lst[l][i] in te):
    #                 te.add(lst[l][i])
    #                 out[lst[l][i]].append(str(lst[l][-2]))
    #                 boolst[l]=False
    #                 dinge[lst[l][i]]-=1
    con=0
    for i in range(0,len(ranklst)-1):
        te = set([])
        for j in range(ranklst[i],ranklst[i+1]):
            for l in range(2,2+k):
                if dinge[lst[j][l]]>0 or (lst[j][l] in te):
                    te.add(lst[j][l])
                    out[lst[j][l]].append(lst[j][-2])
                    dinge[lst[j][l]]-=1
                    lst[j].append(False)
                    con+=1
                    break
    while con:
        for i in lst:
            if not i[-1]:
                lst.remove(i)
                con-=1
    if lst:
        ranka= []
        lst.sort(key=lambda x:(-x[0]-x[1],-x[0]))
        ran,ran1 = 0,1
        for i in range(0,len(lst)-1):
            lst[i].append(ran)
            for j in range(i+1,len(lst)):
                if lst[i][0]==lst[j][0] and (lst[i][0]+lst[i][1])==(lst[j][0]+lst[j][1]):
                    ran1+=1
                    break
                else:
                    ran+=ran1
                    ranka.append(i+1)
                    ran1=1
                    break
        lst[len(lst)-1].append(ran)
        ranka.append(len(lst))
        ranka = [0]+ranka
        for i in range(0,len(ranka)-1):
            te = set([])
            for j in range(ranka[i],ranka[i+1]):
                for l in range(2,2+k):
                    if dinge[lst[j][l]]>0 or (lst[j][l] in te):
                        te.add(lst[j][l])
                        out[lst[j][l]].append(lst[j][-2])
                        dinge[lst[j][l]]-=1
        #                lst[j].append(False)
                        break              
    for i in out:
       if i:
          i.sort()
          print(' '.join(map(str,i)))  
       else:
          print()         
    
    这道题注意,是学生排名由高到低来挑学校,而不是学校按学生排名来挑学生。
    发表于 2018-12-17 00:49:22 回复(0)