P1844 阅览室

· · 题解

有趣的模拟题。

此题用到的方法是使用排序来模拟题目中的优先顺序。

先梳理一下题目。

对于每个时刻,标记每个人该时刻想看的书。然后枚举其他读者,判断冲突并处理,分配这本书。

这里枚举的过程存在冗余计算。发现,题目中的规则是以开始等待的时间为第一关键字,到达时间为第二关键字进行优先分配。即可以用排序简化,直接按顺序依次分配。

具体地,维护当前读者开始等待的时间,每次分配时更新,每个新时刻重新排序。也需要记录每本书的状态以判断可行性。

#include <bits/stdc++.h>
using namespace std;
#define int long long

int T, n, b[1005], ans;

struct reader{
    int arr, k, s[6], t[6], wt;
    bool r[6];
    bool operator<(reader c) const{return (wt != c.wt ? wt < c.wt : arr < c.arr);}
} a[105];

signed main(){
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);

    while(cin >> T >> n){
        for(int i = 1; i <= n; ++ i){
            cin >> a[i].arr >> a[i].k;
            ++ a[i].arr;
            for(int j = 1; j <= a[i].k; ++ j)
                cin >> a[i].s[j] >> a[i].t[j];
            a[i].wt = a[i].arr;
        }
        for(int t = 1; t <= T; ++ t){
            sort(a + 1, a + n + 1);
            for(int i = 1; i <= n; ++ i){
                if(a[i].arr > t || a[i].wt > t)
                    continue;
                for(int j = 1; j <= a[i].k; ++ j)
                    if(b[a[i].s[j]] <= t && !a[i].r[j]){
                        b[a[i].s[j]] = a[i].wt = t + a[i].t[j];
                        ++ ans;
                        a[i].r[j] = 1;
                        break;
                    }
            }
        }
        cout << ans << "\n";
    }

    return 0;
}