PAT (Advanced Level) Practice 1014 Waiting in Line (30分)vector模拟队列

1014 Waiting in Line (30分)

传送门

题意:

N N N 个银行窗口,每个银行窗口的排队区可以等待 M M M个人,一共有 K K K个人按照输入顺序来到银行准备排队办理业务,输入的 K K K个数为每个人自己办理业务需要的时间,排队的规则是先找排队人最少的窗口,如果有多个就找编号最小的窗口,窗口编号为 1 ∼ N 1 \sim N 1N,接着有 Q Q Q个询问,询问每个人办理完业务的时间,时间从早上八点开始,如果这个人在下午五点之前还没有排上队就不能办理它的业务了。

题解:

每个窗口就是一个队列,直接模拟,先把 N ∗ M N*M NM个空位填满,之后每次查找每个队列的第一位(即正在办理业务的那一位)中最快办完的人,然后把这一排的人都减去这个最快的值,为零的即为办完业务的(可能有多个同时完成业务的,需要同时处理),接下来把为零的那个队列队首出队,队尾入队一个正在等候排队的下一位(这里不用判断是不是最小人数,因为我们从小到大遍历,每一次出队的队列一定是下一次入队前队列人数最少且编号最小的队列),直到所有队列为空,用 t o t tot tot记录总时间,每次找到最小办理时间就加上,最后每个人出队的时间就是办理完业务的时间。

代码:

#include <algorithm>
#include <bits/stdc++.h>
#include <iostream>
#include <limits.h>
#include <map>
#include <math.h>
#include <memory.h>
#include <queue>
#include <stack>
#include <stdio.h>
#include <string>
#include <vector>
using namespace std;
#define ms(x, n) memset(x, n, sizeof(x))
#define wht()                                                                  \
    int _;                                                                     \
    for (scanf("%lld", &_); _; _--)
#define For(i, a, b) for (int i = a; i <= (b); i++)
#define Rof(i, a, b) for (int i = a; i >= (b); i--)
#define ioss ios::sync_with_stdio(false)
#define all(a) a.begin(), a.end()
#define int long long

typedef vector<int> vi;
typedef pair<int, int> pii;

const int maxn = 2e6 + 7;
const int maxm = 5e3 + 7;
const int MOD = 1e9 + 7;
const int mod = 998244353;

int min(int a, int b) { return a < b ? a : b; }
int max(int a, int b) { return a > b ? a : b; }
int gcd(int a, int b) { return b ? gcd(b, a % b) : a; }
bool cmp(int a, int b) { return a > b; }

struct node {
    int id, val;
};

const int N = 1e5 + 5;
int n, m, k;
node a[N];
vector<node> g[25];
int ans[N];

bool judge() { // 判断是否结束
    For(i, 1, n) {
        if (g[i].size())
            return 0;
    }
    return 1;
}

void totim(int x) { //分钟数转为时间并输出
    int h, m;
    m = x % 60;
    x /= 60;
    h = x % 60;
    printf("%02lld:%02lld\n", h, m);
}

void work() {
    int q;
    cin >> n >> m >> k >> q;
    For(i, 1, k) {
        int x;
        cin >> x;
        a[i].id = i;
        a[i].val = x;
    }
    int cur = n * m + 1;
    int tot = 0;
    For(j, 0, m - 1) {
        For(i, 1, n) {
            g[i].push_back(a[i + j * n]); //填满N*M个位置
        }
    }

    while (1) {
        if (judge())
            break;
        int mn = INT_MAX, u = -1; //找到最快出队的人
        For(i, 1, n) {
            //			cout<<g[i].size()<<" ";
            if (g[i].size()) {
                if (g[i][0].val < mn) {
                    mn = g[i][0].val;
                    u = i;
                }
            }
        }
        tot += mn; //总时间更新
        For(i, 1, n) {
            if (g[i].size()) {
                g[i][0].val -= mn; //所有正在办理业务的人更新
                if (g[i][0].val == 0) {
                    ans[g[i][0].id] = tot;
                    g[i].erase(g[i].begin()); //出队
                    if (cur <= k)
                        g[i].push_back(a[cur++]); //入队
                }
            }
        }
        //		cout<<"\n";
    }

    For(i, 1, k) {
        ans[i] += 8 * 60;
        //		totim(ans[i] - a[i].val);
        //		totim(ans[i]);
    }

    For(i, 1, q) {
        int x;
        cin >> x;
        if (ans[x] - a[x].val < 17 * 60) //注意:题上说的办理的时间在17点前
            totim(ans[x]); //并不是办理结束的时间在17点前。
        else {
            puts("Sorry");
        }
    }
}

signed main() {
#ifndef ONLINE_JUDGE
    freopen("test.in", "r", stdin);
    freopen("test.out", "w", stdout);
#endif
    work();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值