题目
题目链接:https://pintia.cn/problem-sets/994805342720868352/problems/994805498207911936
思路:
创建一个窗口列表,每个列表维护一个M长度的队列, 以及队列末尾的人服务结束的时间, 逐个插入客户,当有队列不满的时候, 直接插入到当前人数最少的队列;当所有队列都满的时候, 找到队首客户服务时间结束最早的队列,把队首客户弹出,并将当前客户入队.
坑点:
- 不能使用自带的时间类,会超时
- 判断客户是否能被服务是判断其开始服务时间是否早于17点, 这个问题对应3个测试点, 感觉测试点有点神奇.
- 类的成员变量在class{}内的都是声明, 只有当类实例化为对象时才被定义, 但是静态成员变量不依赖于实例, 所以需要在类外单独定义.
代码
#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
class Time {
public:
int hour;
int minute;
Time(int hour = 0, int minute = 0);
Time operator+(const Time &t) const;
Time operator+(const int &t) const;
Time &operator=(const Time &t);
int gethour() { return hour; }
int getminute() {return minute; }
bool less(const Time &t);
};
struct Person {
int service_time;
Time end_time; // the time when the customer leaves queue.
} persons[2000];
class window {
private:
Time back_time; // remark the leave time of the last customer in the queue.
queue<Person> w_queue; // a queue contains persons in queue.
public:
static int capacity; // remark the capacity of queue. this code is a declaration.
window () : back_time(8, 0) { } // initial the back time to be 8:00
static void set_capacity(unsigned int init_capacity); // method to modify the capacity of window class
bool is_full() // whether the queue is full.
{ return w_queue.size() == capacity; }
void enqueue(Person &p); // enqueue persons with updating the back_time and the end_time of person.
void dequeue() { w_queue.pop(); } // dequeue person from front.
Person top() { return w_queue.front(); } // get the front person of queue.
int cur_in_queue() { return w_queue.size(); } // return the number of persons in queue.
};
int window::capacity = 5; // 静态成员变量需要初始化分配内存空间
/**
* switch which window the next customer enqueue.
* If there's queue not full, return the queue index of which the the number of current customers in queue is least.
* If all queues are full, return the queue index in which the front customer leaves first.
*/
int find_smallest_queue(window w[], int size);
int main ()
{
int N, M, K, Q; // N--the number of windows, M--capacity of queue K--people to queue Q-- people to query.
cin >> N >> M >> K >> Q;
window::set_capacity(M);
window* win_list = new window[N];
for (int k = 1; k <= K; k++) {
cin >> persons[k].service_time;
int w_index = find_smallest_queue(win_list, N); // get the queue to enqueue.
if (win_list[w_index].is_full()) { // if the queue is full, dequeue the first customer so that the front time of queue is updated.
win_list[w_index].dequeue();
win_list[w_index].enqueue(persons[k]);
}
else {
win_list[w_index].enqueue(persons[k]); // if the queue isn't full, just enqueue the customer and return the end-service time to this customer.
}
}
Time close_time(17, 0); // set the close time
while (Q--)
{
int query;
cin >> query;
if (persons[query].end_time.less(close_time + persons[query].service_time)) {
printf("%02d:%02d\n", persons[query].end_time.gethour(), persons[query].end_time.getminute());
}
else printf("Sorry\n");
}
getchar();
getchar();
return 0;
}
Time::Time(int hour, int minute) {
this->hour = hour;
this->minute = minute;
}
Time Time::operator+(const Time &t) const
{
Time temp;
temp.hour = this->hour + t.hour;
temp.minute = this->minute + t.minute;
if (temp.minute > 59) {
temp.minute = temp.minute % 60;
temp.hour++;
}
return temp;
}
Time Time::operator+(const int &t) const
{
Time temp(this->hour, this->minute + t);
if (temp.minute > 59) {
temp.hour += temp.minute / 60;
temp.minute = temp.minute % 60;
}
return temp;
}
Time& Time::operator=(const Time &t)
{
this->hour = t.hour;
this->minute = t.minute;
return *this;
}
bool Time::less(const Time &t)
{
if (this->hour < t.hour) return true;
else if (this->hour == t.hour && this->minute < t.minute) return true;
else return false;
}
int find_smallest_queue(window w[], int size)
{
int best_w = 0;
int best_size = window::capacity;
for (int i = 0; i < size; i++)
{
if(!w[i].is_full() && w[i].cur_in_queue() < best_size)
best_w = i;
best_size = w[i].cur_in_queue();
}
if (best_size < window::capacity) return best_w;
best_w = 0;
Time earliest_time(24, 0);
for (int i = 0; i < size; i++)
{
if (w[i].top().end_time.less(earliest_time)) {
best_w = i;
earliest_time = w[i].top().end_time;
}
}
return best_w;
}
void window::set_capacity(unsigned int init_capacity)
{
capacity = init_capacity;
}
void window::enqueue(Person &p)
{
if (w_queue.size() < capacity) {
back_time = back_time + p.service_time;
p.end_time = back_time;
w_queue.push(p);
}
else
throw "enqueue to a full w_queue.";
}
```