UVa212
Use of Hospital Facilities
医院包含手术室和恢复室两种类型的房间,病人需要先在手术室进行手术,然后转移到恢复室中恢复,病人只可能在由于手术室不足而等待,而不回因为恢复室不足而等待。给定每个病人的手术时间和恢复时间,模拟医院的业务流程,并打印每个手术室和每个恢复室的统计信息。
借鉴习题5-13的思路,在每个会发生事件的时间点对病人、手术室和恢复室进行调度即可。这里首先定义可能发生的事件类型,在本题中只需要定义手术室可用事件和ROOM_READY
和ROOM_FINISHED
两种即可,因为题目保证了病人不会因恢复室不足而等待,因此当手术完成后,可以直接将病人转移到可用的编号最小的恢复室中,同时由于病人恢复所用时间是已知的,因此恢复室再次可用的事件也是可以算出来的。定义了事件的类型后,只需要根据题目要求模拟即可。
这道题提交后RTE
后的好多次,是因为最开始是在VSCode
上用g++
编译的,Patient
类的输入运算符没有返回标准输入流,而g++
没有报错,提交后就一直报错,还以为是数组越界了。
还有一个坑就是病人的数量可能为0
,这时统计病房信息的分母就可能为0
,需要特殊处理。
最后,输出格式题目中没有特别说明,因此在代码的最后给出了正确输出的样例。
#include
#include
#include
#include
#include
using namespace std;
enum class EventType
{
ROOM_READY,
ROOM_FINISHED,
};
struct Event
{
EventType et;
int minute;
Event(EventType type, int minute) : et(type), minute(minute) {};
bool operator<(const Event &e) const
{
if (minute < e.minute) return true;
else if (minute == e.minute) {
if (et != e.et && et == EventType::ROOM_READY) return true;
else return false;
}
else return false;
}
};
struct Room
{
int no;
int StartingTime, UsedTime;
size_t PatientIndex;
int AvailableTime, EndTime;
Room(int no, int StartingTime) : no(no), StartingTime(StartingTime),
UsedTime(0), AvailableTime(0), EndTime(0) {};
};
struct Patient
{
string name;
int SurgeyTime, RecoveryTime;
size_t RoomNo, BedNo;
int SurgeryStartingTime, SurgeryEndTime;
int RecoveryStartingTime, RecoveryEndTime;
Patient()
{
RoomNo = 0, BedNo = 0;
SurgeryStartingTime = 0, SurgeryEndTime = 0;
RecoveryStartingTime = 0, RecoveryEndTime = 0;
}
};
istream& operator >> (istream &is, Patient &patient)
{
is >> patient.name >> patient.SurgeyTime >> patient.RecoveryTime;
return is;
}
void ProcessRoomReady(set<Event> &events, vector<Room> &rooms, vector<Room> &beds, vector<Patient> &patients, size_t &PatientIndex, int current)
{
for (Room &room : rooms)
{
if (room.AvailableTime == current) {
if (room.StartingTime == -1) {
room.StartingTime = current;
}
room.UsedTime += patients[PatientIndex].SurgeyTime;
room.PatientIndex = PatientIndex;
room.EndTime = current + patients[PatientIndex].SurgeyTime;
patients[PatientIndex].RoomNo = room.no;
patients[PatientIndex].SurgeryStartingTime = current;
patients[PatientIndex].SurgeryEndTime = patients[PatientIndex].SurgeryStartingTime + patients[PatientIndex].SurgeyTime;
events.insert(Event(EventType::ROOM_FINISHED, room.EndTime));
PatientIndex++;
if (PatientIndex == patients.size()) {
break;
}
}
}
}
void ProcessRoomFinished(set<Event> &events, vector<Room> &rooms, vector<Room> &beds, vector<Patient> &patients,
int current, int O2RTime, int PrepareRoom, int PrepareBed)
{
for (Room &room : rooms)
{
if (room.EndTime == current) {
room.AvailableTime = current + PrepareRoom;
events.insert(Event(EventType::ROOM_READY, room.AvailableTime));
for (Room &bed : beds)
{
if (bed.AvailableTime <= current) {
if (bed.StartingTime == 0) {
bed.StartingTime = current + O2RTime;
}
bed.UsedTime += patients[room.PatientIndex].RecoveryTime;
bed.PatientIndex = room.PatientIndex;
bed.EndTime = current + O2RTime + patients[room.PatientIndex].RecoveryTime;
bed.AvailableTime = bed.EndTime + PrepareBed;
patients[room.PatientIndex].BedNo = bed.no;
patients[room.PatientIndex].RecoveryStartingTime = current + O2RTime;
patients[room.PatientIndex].RecoveryEndTime = patients[room.PatientIndex].RecoveryStartingTime + patients[room.PatientIndex].RecoveryTime;
break;
}
}
}
}
}
void PrintPatient(const vector<Patient> &patients, int StartingHour)
{
cout << " Patient Operating Room Recovery Room" << endl;
cout << " # Name Room# Begin End Bed# Begin End" << endl;
cout << " ------------------------------------------------------" << endl;
for (size_t i = 0; i < patients.size(); i++)
{
cout << setw(2) << setfill(' ') << i + 1 << " ";
cout << patients[i].name << string(9 - patients[i].name.length(), ' ') << ' ';
cout << setw(2) << patients[i].RoomNo << " ";
cout << setw(2) << setfill(' ') << StartingHour + patients[i].SurgeryStartingTime / 60 << ':' << setw(2) << setfill('0') << patients[i].SurgeryStartingTime % 60 << " ";
cout << setw(2) << setfill(' ') << StartingHour + patients[i].SurgeryEndTime / 60 << ':' << setw(2) << setfill('0') << patients[i].SurgeryEndTime % 60 << " ";
cout << setw(2) << setfill(' ') << patients[i].BedNo << " ";
cout << setw(2) << setfill(' ') << StartingHour + patients[i].RecoveryStartingTime / 60 << ':' << setw(2) << setfill('0') << patients[i].RecoveryStartingTime % 60 << " ";
cout << setw(2) << setfill(' ') << StartingHour + patients[i].RecoveryEndTime / 60 << ':' << setw(2) << setfill('0') << patients[i].RecoveryEndTime % 60;
cout << endl;
}
cout << endl;
}
void PrintRoomAndBed(const vector<Patient> &patients, const vector<Room> &rooms, const vector<Room> &beds)
{
int LastLeaveBed = 0;
for (const Patient &patient : patients)
{
if (patient.RecoveryEndTime > LastLeaveBed) {
LastLeaveBed = patient.RecoveryEndTime;
}
}
cout << "Facility Utilization" << endl;
cout << "Type # Minutes % Used" << endl;
cout << "-------------------------" << endl;
for (size_t i = 0; i < rooms.size(); i++)
{
cout << "Room " << setw(2) << setfill(' ') << i + 1 << " " << setw(4) << rooms[i].UsedTime << " ";
cout << fixed << setw(6) << setfill(' ') << setprecision(2);
if (LastLeaveBed == 0) cout << 0.0 << endl;
else cout << 100.0 * rooms[i].UsedTime / LastLeaveBed << endl;
}
for (size_t i = 0; i < beds.size(); i++)
{
cout << "Bed " << setw(2) << setfill(' ') << i + 1 << " " << setw(4) << beds[i].UsedTime << " ";
cout << fixed << setw(6) << setfill(' ') << setprecision(2);
if (LastLeaveBed == 0) cout << 0.0 << endl;
else cout << 100.0 * beds[i].UsedTime / LastLeaveBed << endl;
}
cout << endl;
}
void simiulation(vector<Room> &rooms, vector<Room> &beds, vector<Patient> &patients,
int StartingHour, int O2RTime, int PrepareRoom, int PrepareBed)
{
set<Event> events;
events.insert(Event(EventType::ROOM_READY, 0));
size_t PatientIndex = 0;
while (!events.empty()) {
const Event &event = *events.begin();
switch (event.et)
{
case EventType::ROOM_READY:
if (PatientIndex == patients.size()) {
break;
}
ProcessRoomReady(events, rooms, beds, patients, PatientIndex, event.minute);
break;
case EventType::ROOM_FINISHED:
ProcessRoomFinished(events, rooms, beds, patients, event.minute, O2RTime, PrepareRoom, PrepareBed);
break;
default:
break;
}
events.erase(events.begin());
}
PrintPatient(patients, StartingHour);
PrintRoomAndBed(patients, rooms, beds);
}
int main()
{
int RoomNum, BedNum, StartingHour, O2RTime, PrepareRoom, PrepareBed, PatientNum;
while (cin >> RoomNum) {
cin >> BedNum >> StartingHour >> O2RTime >> PrepareRoom >> PrepareBed >> PatientNum;
vector<Patient> patients;
for (int i = 0; i < PatientNum; i++)
{
Patient patient;
cin >> patient;
patients.push_back(patient);
}
vector<Room> rooms, beds;
for (int i = 0; i < RoomNum; i++)
{
rooms.push_back(Room(i + 1, -1));
}
for (int i = 0; i < BedNum; i++)
{
beds.push_back(Room(i + 1, 0));
}
simiulation(rooms, beds, patients, StartingHour, O2RTime, PrepareRoom, PrepareBed);
}
return 0;
}
/*
5 12 07 5 15 10 16
Jones
28 140
Smith
120 200
Thompson
23 75
Albright
19 82
Poucher
133 209
Comer
74 101
Perry
93 188
Page
111 223
Roggio
69 122
Brigham
42 79
Nute
22 71
Young
38 140
Bush
26 121
Cates
120 248
Johnson
86 181
White
92 140
Patient Operating Room Recovery Room
# Name Room# Begin End Bed# Begin End
------------------------------------------------------
1 Jones 1 7:00 7:28 3 7:33 9:53
2 Smith 2 7:00 9:00 1 9:05 12:25
3 Thompson 3 7:00 7:23 2 7:28 8:43
4 Albright 4 7:00 7:19 1 7:24 8:46
5 Poucher 5 7:00 9:13 5 9:18 12:47
6 Comer 4 7:34 8:48 4 8:53 10:34
7 Perry 3 7:38 9:11 2 9:16 12:24
8 Page 1 7:43 9:34 6 9:39 13:22
9 Roggio 4 9:03 10:12 9 10:17 12:19
10 Brigham 2 9:15 9:57 8 10:02 11:21
11 Nute 3 9:26 9:48 7 9:53 11:04
12 Young 5 9:28 10:06 3 10:11 12:31
13 Bush 1 9:49 10:15 10 10:20 12:21
14 Cates 3 10:03 12:03 8 12:08 16:16
15 Johnson 2 10:12 11:38 4 11:43 14:44
16 White 5 10:21 11:53 7 11:58 14:18
Facility Utilization
Type # Minutes % Used
-------------------------
Room 1 165 29.68
Room 2 248 44.60
Room 3 258 46.40
Room 4 162 29.14
Room 5 263 47.30
Bed 1 282 50.72
Bed 2 263 47.30
Bed 3 280 50.36
Bed 4 282 50.72
Bed 5 209 37.59
Bed 6 223 40.11
Bed 7 211 37.95
Bed 8 327 58.81
Bed 9 122 21.94
Bed 10 121 21.76
Bed 11 0 0.00
Bed 12 0 0.00
*/