题目描述
输入样例
9
0 20
1 15
1 61
2 10
10 5
10 3
30 18
31 25
31 2
3
输出样例
思路
队列模拟
存储结构:使用结构体,存储每一个客户的到达时间和处理时间==(最大为60,大于60的,按60处理)==;用两个数组分别存储每一个窗口的办理人数 和 该窗口结束上一次处理的时间点
具体流程:由于题目给定的顾客顺序是按照时间先后,因此我们顺序处理即可
1.依次遍历每一个窗口,用flag标记该客户是否需要等待。
①如果存在一个窗口,该窗口上一次结束处理的时间 <= 客户到达时间,则客户不用等待,则更新该窗口的处理结束时间和处理人数
②如果不存在,则需要找到结束最快的一个窗口,标记其窗口编号和处理结束时间(用于计算该客户的等待时间)
2.如果本次客户需要等待,用之前找到的最短等待窗口,更新该窗口的处理结束时间和处理人数,计算总的等待时间
3.所有客户处理完成后,遍历存储窗口结束时间的数组,取出最大值,即为最后完成时间
AC代码
#include <bits/stdc++.h>
using namespace std;
const int N = 20;
typedef struct Person
{
int t, p; //到达时间 处理时间
}person;
person p;
queue<person> q;
int cnt[N], complete[N]; //记录每个窗口处理的人数 和 上一次处理完成的时间
int sum_complete, max_wait, last_complete;// 平均等待时间 、最长等待时间、最后完成时间
int main()
{
int n, k;
cin >> n;
for(int i = 0; i < n; i ++)
{
int T, P;
cin >> T >> P;
if(P > 60) P = 60; //题目中要求最大处理时间为60
p = {T, P};
q.push(p); //入队
}
cin >> k;
while(q.size()) //按照顺序,先到先处理
{
p = q.front();
q.pop();
bool flag = true; //标记当前的人是否需要等待,默认需要等待
int min_complete = 0x3f3f3f3f, min_complete_pos = 0; //在需要等待的情况下,我们需要找到上一次结束处理最早的窗口
for(int i = 0; i < k; i ++) //寻找合适的窗口
{
//上一次该窗口结束处理的时间 小于等于 本人的到达时间, 则无需等待
if(complete[i] <= p.t)
{
flag = false;
cnt[i] ++; //该窗口处理的人数+1
complete[i] = p.t + p.p; //更新该窗口结束上一次处理的时间
break;
}
//记录上一次处理完成最早的窗口的结束时间 和 窗口编号
if(min_complete > complete[i])
{
min_complete_pos = i;
min_complete = complete[i];
}
}
//需要等待
if(flag)
{
int temp_wait = min_complete - p.t; //等待的时间为 上一次该窗口结束处理的时间 - 本人到达时间
sum_complete += temp_wait;
max_wait = max(temp_wait, max_wait); //更新最大等待时间
cnt[min_complete_pos] ++; //对应窗口处理人数+1
complete[min_complete_pos] = min_complete + p.p; //更新对应窗口的结束上一次处理的时间
}
}
for(int i = 0; i < k; i ++) last_complete = max(last_complete, complete[i]);
printf("%.1f %d %d\n", sum_complete *1.0 / n, max_wait, last_complete);
for(int i = 0; i < k; i ++)
{
if(i != k - 1) printf("%d ", cnt[i]);
else printf("%d\n", cnt[i]);
}
return 0;
}
欢迎大家批评指正!!!