PAT1080大学院入学「意図を正しく理解することの重要性について-続き」

1080。大学院への入学(30)

浙江省には、2011年に4万件を超える出願が可能な大学院が約100校あると言われています。入学手続きを自動化するプログラムを作成できれば、非常に役立ちます。

各申請者は2つの等級を提供する必要があります:国家入試の等級G Eと面接の等級G I。申請者の最終成績は(G E + G I)/ 2です。入学ルールは次のとおりです。

  • 応募者は、最終的な成績に従ってランク付けされ、ランクリストの上位から1つずつ入学が許可されます。
  • 同点の最終学年がある場合、申請者は、国家入試の学年G Eに従ってランク付けされます。それでも同点の場合、それらのランクは同じでなければなりません。
  • 各志願者はKの選択肢を持つことができ、入場は彼/彼女の選択に従って行われます:ランクリストに従って、それが承認されるのは自分の番です。自分の最も望ましい学校の割り当てを超えない場合は、この学校に入学するか、他の選択肢を1つずつ順番に検討します。希望するすべての学校で拒否された場合、この不幸な申請者は拒否されます。
  • 同順位があり、対応する申請者が同じ学校に申請している場合、割り当てが超過しても、その学校は同じランクのすべての申請者を承認する必要があります。

入力仕様:

各入力ファイルには、1つのテストケースが含まれています。

各ケースは、3つの正の整数を含む行で始まります。N(≤40,000)、応募者の総数。M(≤100)、大学院の総数。K(≤5)、申請者が選択できる選択肢の数。

スペースで区切られた次の行には、M個の正の整数があります。i番目の整数は、それぞれi番目の大学院の割り当てです。

次にN行が続き、それぞれがスペースで区切られた2 + Kの整数を含みます。最初の2つの整数は、それぞれ申請者のG EとG Iです。次のK個の整数は、優先される学校を表します。簡単にするために、学校には0からM-1までの番号が付けられ、志願者には0からN-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

  主なアイデアは、学生をカレッジや大学に配置するプログラムを作成することです。これらの各人には複数のボランティアがいます。各カレッジにも一定の割り当てがあります。入学プロセスはランキングに基づいており、ランキングは所定のルールに基づいています。入学後、生徒数が上限を超えても、同じランキングの生徒は同じ学校に入学できるはずです。

  最初に提出したとき、テストポイント4だけが失敗し、それでもテストに合格しませんでした。他の人のコードを読んだ後、唯一の違いは、私のコードが最初に学生で埋められたすべての大学を調べて、割り当てがあるかどうかを確認していることです。次に、もう一度繰り返して、オーバー登録できるかどうかを判断し、合計2人のボランティアをトラバースします。正しいアプローチは次のとおりです:学生のボランティアが記入した大学を通過し、学生が過剰入学の資格を持っている場合、脳への入学はありません。誰からも隠されないように、私がACにいたとき、私は少し愚かでした。そのため、質問を何度か注意深く読み、間違えたところが元の質問の大胆な部分であることがわかりました。

even if its quota will be exceeded.

  この「でも」の理解に焦点が当てられています。イベントは、BであってもAで発生します。つまり、イベントが発生したかどうかを判断するときに、条件AがBをオーバーライドします。この質問では、「学校は生徒を受け入れる」(イベント)です。「学校が同じランクの生徒を受け入れた」(A)の条件が満たされる場合、「学校に割り当てがある」(B)の条件に関係なく発生します。 。つまり、学校の残りの場所は無視されます。

   この低レベルの理解エラー(エラーとも呼ばれない)を回避するには、経験または注意のレベルを質的に変更する必要があると思います(╯﹏╰)

コードは次のとおりです。

#include <bits/stdc++.h>
using namespace std;
struct node{
    int ge,gi,avg,rank;
    int id,res;
    vector<int> choice;
};
vector<int> quota,lastrank;//lastrank是每所学校上一个录取学生的排名
vector<node> stu;
vector<vector<int> > ans;
int n,m,k;
bool cmp(const node &a,const node &b){
    if(a.avg!=b.avg) return a.avg>b.avg;
    else return a.ge>b.ge;
}
int main(){
    //freopen("input.md","r",stdin);
    scanf("%d%d%d",&n,&m,&k);
    quota.resize(m);
    stu.resize(n);
    ans.resize(m);
    lastrank.resize(m);
    for(int i=0;i<m;i++){
        scanf("%d",&quota[i]);
    }
    for(int i=0;i<n;i++){
        scanf("%d%d",&stu[i].ge,&stu[i].gi);
        stu[i].choice.resize(k);
        for(int j=0;j<k;j++){
            scanf("%d",&stu[i].choice[j]);
        }
        stu[i].avg=stu[i].ge+stu[i].gi;
        stu[i].id=i;
    }
    sort(stu.begin(),stu.end(),cmp);
    stu[0].rank=1;
    for(int i=1;i<n;i++){//根据排序结果对学生赋予排名
        if(stu[i].avg!=stu[i-1].avg)
            stu[i].rank=i+1;
        else if(stu[i].ge!=stu[i-1].ge)
            stu[i].rank=i+1;
        else
            stu[i].rank=stu[i-1].rank;
    }
    for(int i=0;i<n;i++){
        for(int j=0;j<k;j++){
            int sch=stu[i].choice[j];
            //当学生有‘无视剩余名额’录取资格或者学校本身还有名额时
            if(lastrank[sch]==stu[i].rank || quota[sch]>0){
                quota[sch]--;
                stu[i].res=sch;
                ans[sch].push_back(stu[i].id);
                lastrank[sch]=stu[i].rank;
                break;
            }
        }
    }
    for(int i=0;i<ans.size();i++){
        sort(ans[i].begin(),ans[i].end(),[](int &a,int &b)->bool{return a<b;});
        								//这种简单的cmp就用lambda表达式搞定 
        for(int j=0;j<ans[i].size();j++){
            if(j!=0) printf(" ");
            printf("%d",ans[i][j]);
        }
        printf("\n");
    }
    return 0;
}
オリジナルの記事を4件公開しました ・いい ね0です 訪問数44

おすすめ

転載: blog.csdn.net/qq_38399914/article/details/105587397