b_pat_银行排队(全部转化为秒+排序+堆)

Queueing at Bank

假设一家银行有 K 个服务窗口。窗户前面有一条黄线,将等候区分为两部分。
所有客户都必须在黄线后面排队等候,直到轮到他/她服务并且有可用的窗口为止。
假定一个窗口不能被单个客户占用超过 1 小时,即如果某位顾客的业务已经办理了一小时,则立即终止此项业务。
现在给定每个客户的到达时间 T 和业务办理时间 P,请计算所有客户的平均等待时间。
输入格式
第一行包含两个整数 N 和 K,分别表示客户数量以及窗口数量。
接下来 N 行,每行包含两个时间,分别是一个客户的到达时间,用 HH:MM:SS 表示,以及一个客户的业务办理时间 P(单位:分钟)。
HH 在 [00,23] 范围内,MM 和 SS 都在 [00,59] 范围内。
请注意,银行的营业时间为 08:00 至 17:00。
任何人提前到达都必须排队等候至 08:00,而任何人来得太晚(在 17:00:01 或之后到达)都将不被服务也无需计入平均值。
注意只要客户在17:00之前排上队,则即使办理业务时超过17:00,也会被服务。
输出格式
输出平均等待时间(单位:分钟),结果保留一位小数。
注意,从到达银行至开始办理业务这一期间视为等待期间。
数据范围
1≤N≤104,
1≤K≤100

思路
这里的输入时间有时分秒不太好比较,可以全部转化为秒(防止产生小数)
一开始有k个空窗口,每次有客户来的时候,优先安排到先结束办理的窗口内为候选客人服务

#include<bits/stdc++.h>
using namespace std;
const int N=1e4+5, s=8*3600, e=17*3600;
struct node{
    int arrive_time, service_time;
}A[N];
bool cmp(node &a, node &b){
    return a.arrive_time<b.arrive_time;
}
int main() {
    int n,k,hour,minute,second,service_time;;
    scanf("%d%d", &n,&k);
    for (int i=0; i<n; i++) {
        scanf("%d:%d:%d%d", &hour, &minute, &second, &service_time);
        A[i].arrive_time=hour*3600+minute*60+second, A[i].service_time=min(service_time, 60)*60;
    }
    sort(A, A+n, cmp);
    priority_queue<int, vector<int>, greater<int>> q;
    for (int i=0; i<k; i++) q.push(s);  //k个窗口

    int tot=0,cnt=0;
    for (int i=0; i<n; i++) {
        int at=A[i].arrive_time, st=A[i].service_time;
        if (at>e) break;
        int start_time=max(q.top(), at); q.pop();
        tot+=start_time-at; cnt++;
        q.push(start_time+st);
    }   
    printf("%.1f\n", (double) tot/cnt/60.0);
    return 0;
}

Waiting in Line

在黄线以内的区域,每个窗口前都可以排一队人,每队最多可以排 M 个人,当 N 个窗口前的队伍都排满时,第 NM+1 个顾客以及以后的顾客只能在黄线以外的区域等候。黄线外的所有客户统一排成一个长队。
每当客户进入黄线以内时,他会选择到当前排队人数最少的窗口处排队等待办理业务。当多个窗口前排队人数最少时,客户会选择窗口编号更小的窗口处排队等待办理业务。

思路
按照条件找窗口,用use记录每个窗口的总等待时间,id为x的用户如果去了c窗口,则它的完成时间为use[c]+t(t为自己的处理时间)
这题服了,m好像没有真正被用到,只是再算全局限制人数的时候用了一下;其他

#include<bits/stdc++.h>
using namespace std;
const int N=25;
queue<int> win[N];
unordered_map<int, int> mp;

int main() {
    int n,m,k,q; cin>>n>>m>>k>>q;   //n个窗口,每个窗口的最大容量m个,1~k个客户的处理时间,q个查询
    int limit=n*m, use[k+1]; memset(use, 0, sizeof use);

    for (int i=1; i<=k; i++) {
        int t; cin>>t;
        int c=0;
        for (int j=0; j<n; j++) {
            if (i<=limit && win[j].size()<win[c].size()) c=j;
            else if (i>limit && win[j].front()<win[c].front()) c=j;
        }
        if (i>limit) win[c].pop();
        use[c]+=t;
        if (use[c]-t<540) mp[i]=use[c]; //540是指8~17点的总分钟数
        win[c].push(use[c]);
    }

    for (int i=0; i<q; i++) {
        int x; cin>>x;
        if (mp.count(x)) {
            int t=mp[x];
            printf("%02d:%02d\n", t/60+8, t%60);
        } else {
            cout <<"Sorry\n";
        }
     }
    return 0;
}

Mice and Rice

一开始有n个耗子组成了n/m队(m为每队的数量),每次每队最重的胜出,游戏持续到只剩下一只耗子,问最后的排名;

#include<bits/stdc++.h>
using namespace std;
struct node {
    int oIdx, w, rk, init_pos; //原始下标、体重、排名、游戏开始时的位置
};
bool cmp(node& a, node& b) {
    return a.init_pos<b.init_pos;
}
bool cmp1(node& a, node& b) {
    return a.oIdx<b.oIdx;
}
struct cmp_in_pq{
    bool operator()(node& a, node& b){
        return a.w<b.w;
    }
};
int main() {
    std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    int n,m,id; cin>>n>>m; //n老鼠的数量,m每支队伍的总人树
    node A[n];
    for (int i=0; i<n; i++) cin>>A[i].w, A[i].oIdx=i;
    for (int i=0; i<n; i++) cin>>id, A[id].init_pos=i; //编号为id的老鼠在位置i
    sort(A, A+n, cmp);      //将老鼠排成题目给定的初始序列,这样入队才符合题目需求

    queue<node> q; for (int i=0; i<n; i++) q.push(A[i]);
    priority_queue<node, vector<node>, cmp_in_pq> maxQ; 
    
    while (q.size()>1) {    //一共有g=q.size()/m组
        int sz=q.size(), g=sz/m+(sz%m?1:0), rk=g+1;
        for (int i=0; i<g; i++) {
            for (int j=0; j<m && i*m+j<sz; j++) {
                maxQ.push(q.front()); q.pop();  //将每组的老鼠进堆,
            }
            q.push(maxQ.top()); maxQ.pop(); //将每一组最肥的老鼠重新进堆(晋级)
            while (!maxQ.empty()) {
                A[maxQ.top().init_pos].rk=rk; maxQ.pop(); //假如有4对,则一定会有4只老鼠晋级,则剩下的老鼠都是第5名
            }
        }
    }
    A[q.front().init_pos].rk=1;
    sort(A, A+n, cmp1);
    for (int i=0; i<n; i++) {
        printf("%d", A[i].rk);
        if (i!=n-1) printf(" ");
    }
    return 0;
}
posted @ 2020-09-12 10:12  童年の波鞋  阅读(206)  评论(0编辑  收藏  举报