U192222匹配(北大附中新春公开赛2022T4)

(文章目录)


前言

话说没想到T4出了个模拟,(大雾 我觉得比赛难度应该是T1-T4-T3-T2吧,T4没有那么难。也可能是最近模拟做多了?


题目大意

题目有点长放个链接。题目传送门


思路

读了一下题就能看出是模拟了。做模拟可以在纸上过几遍样例,题读两到三遍,确保没拉下啥,之后调的时间可比多读几遍题多。

再没有达到条件前就一直循环。退出的条件题目里也说了,就是没有一个 h[i]=0h[i]=0

之后没满足之前:
首先定义一个数组goodgood[i]good[i] 为第 ii 个人是否匹配成功,如果匹配了就跳过不发。再然后有一个数组numnum[i]num[i] 为第 ii 个人当前的选择公司。每一次 +1+1,也就是上一次一定被拒绝了,没有匹配成功。之后就可以知道这一次选的公司是f[i][now[i],然后就去按照题意比较了。

注意:map的空间复杂度也要算算,为使用的空间大小,也就是 O([]里的空间复杂度使用的元素个数\mathcal{O}(\text{[]里的空间复杂度}*\text{使用的元素个数},在本题里如果用 pair<ll,ll>表示公司和排名的话空间复杂度就是 O(16n2)\mathcal{O}(16n^2),开long long 就是大约400MB,MLE欢迎你。所以只能 O(n)\mathcal{O}(n) 查询排名了(悲伤)。在用map之前也要在空间复杂度那里算一下map的空间复杂度,或者时空间复杂度允许的条件下能不用map就不用。


代码

#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
typedef long long ll;
const ll MAXN=5001;
ll f[MAXN][MAXN],g[MAXN][MAXN],now[MAXN],h[MAXN];//分别为f,g,每一个毕业生没被拒绝的位置,h
bool good[MAXN];//是否完成配对(包括暂时)
ll n,seed;
ll get_rank(ll k,ll i){
    for (int j = 1; j <=n ; ++j) {
        if(g[k][j]==i){
            return j;
        }
    }
    return 0;
}
int main(){
    cin>>n>>seed;
    srand(seed);
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++) f[i][j] = j;
        random_shuffle(f[i]+1, f[i]+1+n);
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++) g[i][j] = j;
        random_shuffle(g[i]+1, g[i]+1+n);
    }
    while (true){
        for (int i = 1; i <=n ; ++i) {
            //遍历所有员工
            if(good[i]){
                continue;
            }
            now[i]++;
            ll sent=f[i][now[i]];
            if(h[sent]==0){
                h[sent]=i;
            }else{
                if(get_rank(sent,h[sent])>get_rank(sent,i)){
                    h[sent]=i;
                }
            }
        }
        memset(good, false,sizeof(good));
        for (int i = 1; i <=n ; ++i) {
            if(h[i]){
                good[h[i]]= true;
            }
        }
        bool fin= true;
        for (int i = 1; i <=n ; ++i) {
            if(h[i]==0){
                fin= false;
                break;
            }
        }
        if(fin){
            break;
        }
    }
    for (int i = 1; i <=n ; ++i) {
        cout<<h[i]<<" ";
    }
    return 0;
}


总结

做了一道大模拟。同时知道了map的空间复杂度是存的东西的总大小,不要无视map的空间复杂度。