PAT甲级1014 Waiting in Line

模拟题。感觉跟某次 CSP 的第四题有点像,是它的简化版。

维护 n 个队列,长度均 <= m,每个队列记录其下一个客户可以开始的时间(或者称为当前正在处理的客户的完成时间)。每次遍历所有队列,找出完成时间最早的那个,更新相应的客户的完成时间,并将其移除出该队列。同时,若还有客户在黄线以外,则将其加入该队列(这样就能保证 <= m 了)。反复执行,直到遍历所有队列后发现,所有队列的最早完成时间都在 17:00 之后了,这时,坑来了。即使银行 17:00 关门,但仍要等待 17:00 前就开始的客户的业务完成。所以,需要遍历一遍所有队列,将所有已经开始(意味着开始时间 <= 16:59)的客户的完成时间进行更新,然后退出循环。此时,17:00 (含)以后才能开始的客户都无法开始了(”Sorry“),而 17:00 以前开始的客户都有了结束的时间。

#include 
using namespace std;
const int maxn = 20+2;
const int maxk = 1e3+3;
const int maxt = 540;
struct Window {
    int next; //下一个客户可以开始处理的时间
    deque line; //队列

    void push_back(int x) {
        line.push_back(x);
    }

    void pop_front() {
        line.pop_front();
    }

    int front() {
        return line.front();
    }

    int size() {
        return line.size();
    }
} w[maxn];
int n, m, k, q;
int t[maxk];
int ans[maxk];

void read() {
    scanf("%d%d%d%d", &n, &m, &k, &q);
    for (int i = 1; i <= k; ++i) {
        scanf("%d", &t[i]);
        if (i <= n*m) {
            w[(i-1)%n].push_back(i);
        }
    }
}

void solve() {
    int nextt, nextw;
    int curk = min(n*m, k); //n*m可能大于k
    while (true) {
        nextt = maxt+1;
        nextw = -1;
        for (int i = 0; i < n; ++i) {
            if (!w[i].size()) continue; //队列已经空了,不检查

            int temp = w[i].next + t[w[i].front()]; //队首完成时间
            if (nextt > temp) {
                nextt = temp;
                nextw = i;
            }
        }

        if (nextt > maxt || nextw == -1) { //没有发现能在17:00前加入的
            // 将在17:00加入的,并还没有完成的,计算完成时间
            for (int i = 0; i < n; ++i) { 
                if (!w[i].size() || w[i].next >= maxt) continue;

                int temp = w[i].next + t[w[i].front()];
                ans[w[i].front()] = temp;
            }
            // 之后的都是在17:00后才能加入的了,银行已经关门,结束
            break;
        }

        w[nextw].next = nextt;
        ans[w[nextw].front()] = nextt;
        w[nextw].pop_front();
        if (++curk <= k) { //如果还有人没加入队列
            w[nextw].push_back(curk);
        }
    }
}

void query() {
    while (q--) {
        int i;
        scanf("%d", &i);
        if (ans[i]) {
            printf("%.02d:%.02d\n", ans[i]/60+8, ans[i]%60);
        } else {
            printf("Sorry\n");
        }
    }
}

int main() {
    read();
    solve();
    query();
    return 0;
}

 

你可能感兴趣的:(PAT甲级题解)