/
1026.cpp
301 lines (275 loc) · 7.17 KB
/
1026.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
/*
http://www.nowcoder.com/discuss/391
超级麻烦的模拟题。
有乒乓球桌子,每个人来了要说玩多长时间。桌子有普通桌子和VIP桌子。可以认为普通人和VIP在两个不同的队列里,有空桌的话VIP优先,并且VIP优先进入VIP的桌子。还有一些限制每个人不能玩超过两个小时而且没有VIP的时候,普通人也可以用VIP的桌子,VIP如果没有VIP桌子可以用普通人的桌子——总之很多规则,最后看一下每个人玩多久,每个桌子支持了多少人。
我们用事件驱动的方法。
事件包括 :
(1) 时间
(2) 人的id或者桌子的id
(3) 人的id表示人来了,桌子的id表示桌子腾空
我们看一下如何处理这些事件
我们把所有事件按照时间顺序排序,并且同一时间里优先考虑先来人,这样腾出桌子后,能使用这个桌子的人已经在等着呢。
(1) 腾空桌子比较简单
(1.1)把桌子加入到对应集合(VIP桌子和非VIP桌子)
(1.2)考虑是否能进人, 如果有VIP等并且有VIP的桌子,就给VIP分配VIP的桌子(编号最小的)
(1.3) 至此,要么没有VIP的桌子,要么没有VIP人,那么所有人“平等”分配桌子
(2) VIP人来
(2.1) 有VIP的桌子,就给他分配VIP的桌子
(2.2) 没有VIP的桌子,有普通的桌子,给他分配普通桌子
(2.3) 桌子全满,进入VIP等候队列
(3)普通人来
(3.1) 有空桌子(无论是否是VIP桌子)就分配给他——注意这是题目的坑所在,普通人只要有桌子,就可以分配给他一个编号最小的桌子,因为有空桌子一定没有人在等
(3.2) 进入普通的等候队列
关于(1.3)如何平等?
我们可以支持选一个来的最早的人,尽管有两种队列,我们从VIP人和普通人里选一个来得最早的就可以了——题目说没有两个人同时到
如何选一个编号最小的桌子? 和选人一样,从两种桌子集合里面选一个最小的就可以了。
至于集合,可以用set<int>来做,begin就是最小的,我们可以存两种空桌子的id, 还有两种排队的人的id,注意存人的id,主要要存他什么时候来的,所以要存pair<int,int> 表示来的时间和id,因为第一维才是最重要的。
关于 分配桌子后事件的变化, 一个人被分配了一张桌子,我们知道他玩的时间,自然知道他离开桌子的时间,所以我们在事件队列里加一个腾空桌子的事件。总之,就是每满足一个人,就计算他离开的时间加入事件队列。
所以事件是动态的,需要动态按照时间顺序排序,所以自然就用堆、优先队列这种数据结构,我用了优先队列。
time, id, time表示时间,id和类型。如果类型是0,表示id是腾空桌子的id,否则type是1表示id是来的人的id。
还有一个坑就是每个人玩的时间不要超过两个小时——但是输入请求有超过两个小时的,我们需要自己把它变为两个小时(申请玩的时间和120分钟取最小值)。
代码很长: 关键还是要理解上述描述的,选人,选桌,处理时间,处理VIP的过程,理解起来就方便了。
*/
#include <iostream>
#include <queue>
#include <stdio.h>
#include <vector>
#include <set>
using namespace std;
const int close_time = 21*3600;
int N, K, M;
vector<int> play_time; /* play time of each pair*/
vector<bool> is_vip_player;
vector<bool> is_vip_table;
set<int> ord_table; /* table index*/
set<int> vip_table; /* table index*/
set< pair<int, int> > vip_player; /* arrive_time , play_time*/
set< pair<int, int> > ord_player; /* arrive_time , play_time*/
vector<int> nums; /* nums of pairs played on each table*/
typedef struct node
{
int time;
int id;
int type; /* 0->table free, 1->people come*/
}node;
priority_queue<node> affairs;
bool operator<(const node &A, const node &B)
{
if (A.time != B.time)
{
return A.time > B.time;
}
else
{
return A.type < B.type;
}
}
void freeTable(int index)
{
if (is_vip_table[index])
{
vip_table.insert(index);
}
else
{
ord_table.insert(index);
}
}
void printTime(int arrive_time, int serve_time)
{
printf("%02d:%02d:%02d %02d:%02d:%02d ", arrive_time/3600, arrive_time/60%60, arrive_time%60,
serve_time/3600, serve_time/60%60, serve_time%60);
printf("%d\n", (serve_time-arrive_time+30)/60);
}
pair<int, int> getPlayer()
{
pair<int, int> ret;
if (vip_player.empty())
{
ret = *ord_player.begin();
ord_player.erase(ord_player.begin());
return ret;
}
if (ord_player.empty())
{
ret = *vip_player.begin();
vip_player.erase(vip_player.begin());
return ret;
}
if (ord_player.begin()->first < vip_player.begin()->first)
{
ret = *ord_player.begin();
ord_player.erase(ord_player.begin());
}
else
{
ret = *vip_player.begin();
vip_player.erase(vip_player.begin());
}
return ret;
}
int getTable()
{
int ret;
if (vip_table.empty())
{
ret = *ord_table.begin();
ord_table.erase(ord_table.begin());
return ret;
}
if (ord_table.empty())
{
ret = *vip_table.begin();
vip_table.erase(vip_table.begin());
return ret;
}
if (*vip_table.begin() < *ord_table.begin())
{
ret = *vip_table.begin();
vip_table.erase(vip_table.begin());
}
else
{
ret = *ord_table.begin();
ord_table.erase(ord_table.begin());
}
return ret;
}
int main()
{
int hh, mm, ss, viptag, index, nowtime;
node temp;
pair<int, int> tplayer;
cin >> N;
play_time.resize(N);
is_vip_player.resize(N);
for (int i = 0; i != N; ++i)
{
scanf("%d:%d:%d %d %d", &hh, &mm, &ss, &play_time[i], &viptag);
is_vip_player[i] = (bool)viptag;
play_time[i] = 60 * min(play_time[i], 120);
temp.time = hh*3600 + mm*60 + ss;
temp.id = i;
temp.type = 1;
affairs.push(temp);
}
cin >> K >> M;
nums.resize(K);
is_vip_table.resize(K);
for (int i = 0; i != M; ++i)
{
cin >> index;
is_vip_table[--index] = true;
}
for (int i = 0; i != K; ++i)
{
if (is_vip_table[i])
{
vip_table.insert(i);
}
else
{
ord_table.insert(i);
}
}
while (!affairs.empty())
{
temp = affairs.top();
affairs.pop();
nowtime = temp.time;
if (nowtime >= close_time)
{
break;
}
if (0 == temp.type)
{
freeTable(temp.id);
/* 多个桌子可能同时释放*/
while (!affairs.empty() && affairs.top().type == 0 && affairs.top().time == nowtime)
{
freeTable(affairs.top().id);
affairs.pop();
}
while (!vip_table.empty() && !vip_player.empty())
{
temp.time = nowtime + vip_player.begin()->second;
temp.type = 0;
temp.id = *vip_table.begin();
++nums[temp.id];
printTime(vip_player.begin()->first, nowtime);
affairs.push(temp);
vip_table.erase(vip_table.begin());
vip_player.erase(vip_player.begin());
}
while ((!ord_player.empty() || !vip_player.empty()) && (!ord_table.empty() || !vip_table.empty()))
{
tplayer = getPlayer();
temp.time = nowtime + tplayer.second;
temp.type = 0;
temp.id = getTable();
++nums[temp.id];
printTime(tplayer.first, nowtime);
affairs.push(temp);
}
}
else
{
if (is_vip_player[temp.id])
{
if (!vip_table.empty())
{
temp.time = nowtime + play_time[temp.id];
printTime(nowtime, nowtime);
temp.type = 0;
temp.id = *vip_table.begin();
++nums[temp.id];
affairs.push(temp);
vip_table.erase(vip_table.begin());
}
else
{
if (!ord_table.empty())
{
temp.time = nowtime + play_time[temp.id];
printTime(nowtime, nowtime);
temp.type = 0;
temp.id = *ord_table.begin();
++nums[temp.id];
affairs.push(temp);
ord_table.erase(ord_table.begin());
}
else
{
vip_player.insert(make_pair(nowtime, play_time[temp.id]));
}
}
}
else
{
if (!vip_table.empty() || !ord_table.empty())
{
temp.time = nowtime + play_time[temp.id];
printTime(nowtime, nowtime);
temp.type = 0;
temp.id = getTable();
++nums[temp.id];
affairs.push(temp);
}
else
{
ord_player.insert(make_pair(nowtime, play_time[temp.id]));
}
}
}
}
for (unsigned int i = 0; i != nums.size(); ++i)
{
if (0 != i)
{
cout << ' ';
}
cout << nums[i];
}
cout << endl;
return 0;
}