PAT甲级1014 队列模拟题
解题思路:
很明显这是一个模拟题,个人觉得很经典。首先,利用nowTime
的递增来模拟时间的增长,真正的难点在于寻找一个合适模拟方式,使得题目要求入队方式完美实现,并且还可以精准的计算时间。在这里,用N个队列模拟服务区,用一个wait
模拟等待区,只要服务区一有空闲,等待区的人立刻补充上。因为服务区是从1~N
进行循环检查的,所以完全可以满足题目中要求从低的开始补齐,而且服务区出队的时候,立刻有等待的人补充上。对于时间的控制来说,不是使用DP,刚开始还想用DP来解决,后来发现思路是错的;应该是利用时间模拟的过程中,动态地进行局部的时间计算,即每次只计算队头的时间,这样,在模拟结束的时候,就可以获取所有的时间结果了。
其他的一些注意事项在代码的注释中写出了。
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 21;
const int MAXK = 1005;
int N, M, K, Q;
struct Person {
int id, serverTime; // 编号 服务时长
int BeginTime, EndTime; // 开始结束时间
Person(): BeginTime(0), EndTime(-1), serverTime(0), id(0) {} // EndTime为-1说明sorry
} Per[MAXK];
queue<Person>line[MAXN], wait;
int main() {
cin >> N >> M >> K >> Q;
int cap = N * M;
for(int i = 1; i <= K; ++i) { // 输入时间部分
cin >> Per[i].serverTime;
Per[i].id = i;
if(i <= N) {
Per[i].EndTime = Per[i].serverTime; // 每个窗口第一个排上队的肯定能服务完
}
if(i <= N * M) { // 人先把缓冲服务区加满
line[(i - 1) % N + 1].push(Per[i]); // 注意这种取整运算的技巧
} else { // 等待队列
wait.push(Per[i]);
}
}
int countC = K;
int nowTime = 0, closeTime = 9 * 60;
while(nowTime < closeTime && countC) { // 时间没结束,而且有人在服务
nowTime++;
for(int i = 1; i <= N; ++i) {
if(line[i].empty()) { // 处理出现空窗口的情况
continue;
}
Person head = line[i].front();
// 注意第二个判断条件,为了控制测试数据中最后的那个例子类型的
if(head.EndTime <= nowTime || head.EndTime > closeTime) {
line[i].pop();
countC--;
// 下面两行完成时间更替
line[i].front().BeginTime = head.EndTime;
line[i].front().EndTime = head.EndTime + line[i].front().serverTime;
// 完成数据存储
Per[head.id].BeginTime = head.BeginTime;
Per[head.id].EndTime = head.EndTime;
if(!wait.empty()) { // 如果还有人等待,就立即加入进来
line[i].push(wait.front());
wait.pop();
}
}
}
}
int q;
for(int i = 1; i <= Q; ++i) {
cin >> q;
if(Per[q].EndTime == -1) {
cout << "Sorry" << endl;
} else { // printf输出的技巧
printf("%02d:%02d\n", Per[q].EndTime / 60 + 8, Per[q].EndTime % 60);
}
}
return 0;
}
/*
测试案例,注意最后那个例子,结束时间超出17:00没事
输入:
2 2 9 9
1 2 6 4 3 1 9 100 534
1 2 3 4 5 6 7 8 9
输出:
08:01
08:02
08:07
08:06
08:10
08:07
08:16
09:50
17:10
*/
一些小感想:
个人感觉,题目真的很好,学会了一种新方式。虽然刚开始接触这题时,花了灰常长的时间,,,在参考了dalao的blog后,实现了。。每日都要有进步啊