PAT_甲级_1080 Graduate Admission (30point(s)) (C++)【考生录取模拟】

目录

1,题目描述

 题目大意

2,思路

数据结构

算法

3,AC代码

4,解题过程

第一搏

第二搏


1,题目描述

  •  proceed:继续做(或从事、进行); 接着做; 继而做; 行进;
  • quota:定量,指标;

Sample Input:

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

 

Sample Output:

0 10
3
5 6 7
2 8

1 4

 题目大意

模拟考生报志愿录取的情形。每名考生可报一定数目的志愿,学校则根据报名的学生,按照排名次序,若名额未满则录取,若已录取满,但下一名考生的totlaG和GE均与该校录取的最后一名考生相等,则仍会录取。

注意,排名优先:按照排名的先后顺序,确定一个考生的录取状态(录取/未录取)后,再处理下一名考生。

 

2,思路

数据结构

  • int quota[101]:每个学校招生人数;
  • struct node{
        int id, GE, totalG;
        int sel[6];//选择的志愿
    };       存放每名考生的信息;
  • vector<int> school[101]:存放每个学校录取的考生id;
  • vector<node> student:存放所有考生的信息;
  • node lastStu[101]:存放每个学校 录取的最后一名学生

算法

  1. 将所有考生的数据读入student中,并根据设计的排序函数cmp1,对学生排序: 
  2. 按照对学生排序后的顺序,依次处理每位考生的志愿(志愿未满 / 志愿已满,但成绩与最后一位录取的考生相同 / 其他),确认录取状态后,再处理下一位考生:
  3. 将每个学校录取的考生,按照学号升序排序并输出:

 

3,AC代码

#include<bits/stdc++.h>
using namespace std;
int N, M, K;               //N报名人数 M学校数目 K志愿数目
int quota[101];            //每个学校招生人数
struct node{
    int id, GE, totalG;
    int sel[6];            //选择的志愿
};
vector<int> school[101];   //每个学校一个vector 存放录取学生的id
vector<node> student;

bool cmp1(node a, node b){
    if(a.totalG != b.totalG)
        return a.totalG > b.totalG;
    else{
        if(a.GE != b.GE)
            return a.GE > b.GE;
        else
            return a.id < b.id;//没有此规定 但为了保证逻辑严密
    }
}
int main(){
#ifdef ONLINE_JUDGE
#else
    freopen("1.txt", "r", stdin);
#endif // ONLINE_JUDGE
    scanf("%d %d %d", &N, &M, &K);
    for(int i = 0; i < M; i++)
        scanf("%d", &quota[i]);
    int GE, GI;
    int sel[6];
    node n;
    for(int i = 0; i < N; i++){
        scanf("%d %d", &GE, &GI);
        n.id = i;
        n.GE = GE;
        n.totalG = GE + GI;
        for(int j = 0; j < K; j++) scanf("%d", &n.sel[j]);
        student.push_back(n);
    }
    sort(student.begin(), student.end(), cmp1);
    
    node lastStu[101];                      //存放每个学校 录取的最后一名学生
    for(int i = 0; i < student.size(); i++){
        for(int j = 0; j < K; j++){
            int sch = student[i].sel[j];
            if(school[sch].size() < quota[sch]){
                school[sch].push_back(student[i].id);
                lastStu[sch] = student[i];  //更新最后一名录取的学生
                break;                      //录取成功
            }else if(student[i].totalG == lastStu[sch].totalG &&
                    student[i].GE == lastStu[sch].GE){  //名额已满 但排名相同
                school[sch].push_back(student[i].id);
                break;                      //录取成功
            }
        }
    }
    for(int i = 0; i < M; i++){
        sort(school[i].begin(), school[i].end());
        if(school[i].size() != 0){
            printf("%d", school[i][0]);
            for(int j = 1; j < school[i].size(); j++)
                printf(" %d", school[i][j]);
        }
        printf("\n");
    }
    return 0;
}

 

4,解题过程

第一搏

有一个疑问,就是如果第几轮选拔后,学校的名额已满,但是下一轮选拔中的第一名与上一轮的最后一名成绩相同(区别是选志愿的顺序)怎么办?

于是我先按照志愿优先的方法(依次考虑所有人的志愿,以第一志愿为例,假设一名考生,就算排名靠前,如果他第一志愿的学校已经录取满,则只能等待第二志愿了。而就算最后一名,他的第一志愿学校未录取满,他仍可以被录取)

#include<bits/stdc++.h>
using namespace std;
int N, M, K;//N报名人数 M学校数目 K志愿数目
int quota[101];//每个学校招生人数
struct node{
    int id, GE, totalG;
    int sel[6];//选择的志愿
    bool admit;
};

vector<int> school[101];//每个学校一个vector 存放录取学生的id
vector<node> student;
bool cmp1(node a, node b){
    if(a.totalG != b.totalG)
        return a.totalG > b.totalG;
    else{
        if(a.GE != b.GE)
            return a.GE > b.GE;
        else
            return a.id < b.id;//没有此规定 但为了保证逻辑严密
    }
}

int main(){
#ifdef ONLINE_JUDGE
#else
    freopen("1.txt", "r", stdin);
#endif // ONLINE_JUDGE
    scanf("%d %d %d", &N, &M, &K);
    for(int i = 0; i < M; i++)
        scanf("%d", &quota[i]);

    int GE, GI;
    int sel[6];
    node n;
    for(int i = 0; i < N; i++){
        scanf("%d %d", &GE, &GI);
        n.id = i;
        n.GE = GE;
        n.totalG = GE + GI;
        n.admit = false;
        for(int j = 0; j < K; j++) scanf("%d", &n.sel[j]);
        student.push_back(n);
    }
    sort(student.begin(), student.end(), cmp1);

    bool full[101];//学校在一轮的录取中是否已经录取满
    node lastStu[101];//存放每个学校 每轮录取的最后一名学生
    for(int i = 0; i < K; i++){//K轮选课
        vector<int> fullSch;//本轮录取满的学校
        for(int j = 0; j < student.size(); j++){
            if(student[j].admit == false){

                int sch = student[j].sel[i];
                if(!full[sch]){//该学校上一轮未选满
                    if(school[sch].size() < quota[sch]){//该学校本轮中还有名额
                        school[sch].push_back(student[j].id);
                        student[j].admit = true;
                        lastStu[sch] = student[j];
                    }
                    else if(student[j].totalG == lastStu[sch].totalG &&
                            student[j].GE == lastStu[sch].GE){//名额已满 但排名相同
                        fullSch.push_back(sch);
                        school[sch].push_back(student[j].id);
                        student[j].admit = true;
                    }
                }

            }
        }
        for(auto a : fullSch){//将本轮已录取满的学校做标记
            full[a] = true;
        }
        fullSch.clear();//每轮结束后清空
    }

    for(int i = 0; i < M; i++){
        sort(school[i].begin(), school[i].end());
        if(school[i].size() != 0){
            printf("%d", school[i][0]);
            for(int j = 1; j < school[i].size(); j++)
                printf(" %d", school[i][j]);
        }
        printf("\n");
    }
    return 0;
}

没办法,,,手动演算了一遍,按照原先设想的算法规则,确实应该是这样。

看来是规则没理解清楚。。。

 

第二搏

根据演算过程,重新设计了规则:

排名优先,按照排名依次考虑每个学生,若第一志愿已满,则依次考虑其他志愿,直到被录取所有志愿均已满未被录取,则考虑下一位考生。

那就很简单了嘛<( ̄ c ̄)y▂ξ

逻辑更加直白了。

一道大题做出了两道大题的感觉,我很快乐/(ㄒoㄒ)/~~

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
select * from ( SELECT P.PATIENT_ID, P.VISIT_ID, PM.NAME, PM.SEX, P.ADMISSION_DATE_TIME, ( SELECT TOP 1 DP.DEPT_NAME FROM DEPT_DICT DP WHERE DP.DEPT_CODE = P.DEPT_ADMISSION_TO ) AS DEPT_ADM, P.DISCHARGE_DATE_TIME, ( SELECT TOP 1 DP.DEPT_NAME FROM DEPT_DICT DP WHERE DP.DEPT_CODE = P.DEPT_DISCHARGE_FROM ) AS DEPT_DIS, DATEDIFF( DAY, P.ADMISSION_DATE_TIME, P.DISCHARGE_DATE_TIME ) AS INPAT_DAYS, P.DOCTOR_IN_CHARGE --datediff(day, P.ADMISSION_DATE_TIME,P.DISCHARGE_DATE_TIME) as zyts FROM PAT_VISIT P INNER JOIN PAT_MASTER_INDEX PM ON PM.PATIENT_ID = P.PATIENT_ID WHERE select * from ( SELECT P.PATIENT_ID, P.VISIT_ID, PM.NAME, PM.SEX, P.ADMISSION_DATE_TIME, ( SELECT TOP 1 DP.DEPT_NAME FROM DEPT_DICT DP WHERE DP.DEPT_CODE = P.DEPT_ADMISSION_TO ) AS DEPT_ADM, P.DISCHARGE_DATE_TIME, ( SELECT TOP 1 DP.DEPT_NAME FROM DEPT_DICT DP WHERE DP.DEPT_CODE = P.DEPT_DISCHARGE_FROM ) AS DEPT_DIS, DATEDIFF( DAY, P.ADMISSION_DATE_TIME, P.DISCHARGE_DATE_TIME ) AS INPAT_DAYS, P.DOCTOR_IN_CHARGE --datediff(day, P.ADMISSION_DATE_TIME,P.DISCHARGE_DATE_TIME) as zyts FROM PAT_VISIT P INNER JOIN PAT_MASTER_INDEX PM ON PM.PATIENT_ID = P.PATIENT_ID WHERE P.DISCHARGE_DATE_TIME >= '2016-01-01' AND P.DISCHARGE_DATE_TIME < = '2023-07-10' AND DATEDIFF( DAY,P.ADMISSION_DATE_TIME, P.DISCHARGE_DATE_TIME ) >= 30 ) t order by inpat_days desc P.DISCHARGE_DATE_TIME >= '2016-01-01' AND P.DISCHARGE_DATE_TIME < = '2023-07-10' AND DATEDIFF( DAY,P.ADMISSION_DATE_TIME, P.DISCHARGE_DATE_TIME ) >= 30 ) t order by inpat_days desc 帮我把这段sql优化一下
07-25
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值